38 Commits

Author SHA1 Message Date
Jack Grigg 9329e31dd3 v0.5.1
Publish release binaries / Publish for macos-arm64 (push) Has been cancelled
Publish release binaries / Publish for macos-x86_64 (push) Has been cancelled
Publish release binaries / Publish for linux (push) Has been cancelled
Publish release binaries / Publish for windows (push) Has been cancelled
Publish release binaries / Debian linux (push) Has been cancelled
2026-04-08 04:27:00 +01:00
Jack Grigg ac22ae1df1 Merge tag 'v0.5.0' into detect-critical-extensions 2026-04-08 04:21:39 +01:00
Jack Grigg 23a1f61e5a v0.4.1
CI checks / Test on linux (push) Has been cancelled
CI checks / Test on macos (push) Has been cancelled
CI checks / Test on windows (push) Has been cancelled
CI checks / Code coverage (push) Has been cancelled
CI checks / Intra-doc links (push) Has been cancelled
CI checks / Rustfmt (push) Has been cancelled
Publish release binaries / Publish for macos-arm64 (push) Has been cancelled
Publish release binaries / Publish for macos-x86_64 (push) Has been cancelled
Publish release binaries / Publish for linux (push) Has been cancelled
Publish release binaries / Publish for windows (push) Has been cancelled
Publish release binaries / Debian linux (push) Has been cancelled
2026-04-08 04:20:54 +01:00
Jack Grigg eb945b2849 Merge tag 'v0.4.0' into detect-critical-extensions 2026-04-08 04:16:00 +01:00
Jack Grigg bf081835c4 Release 0.3.4
CI checks / Test on linux (push) Has been cancelled
CI checks / Test on macos (push) Has been cancelled
CI checks / Test on windows (push) Has been cancelled
CI checks / Clippy (1.56.0) (push) Has been cancelled
CI checks / Clippy (nightly) (push) Has been cancelled
CI checks / Code coverage (push) Has been cancelled
CI checks / Intra-doc links (push) Has been cancelled
CI checks / Rustfmt (push) Has been cancelled
Publish release binaries / Publish for macos-arm64 (push) Has been cancelled
Publish release binaries / Publish for macos-x86_64 (push) Has been cancelled
Publish release binaries / Publish for linux (push) Has been cancelled
Publish release binaries / Publish for windows (push) Has been cancelled
Publish release binaries / Debian linux (push) Has been cancelled
2026-04-08 04:14:54 +01:00
Jack Grigg 9503f406ae Reject identities with unrecognised critical extensions
We don't know how to correctly use these identities. In particular, some
identities store parts of their private key material in certificate
extensions to work around hardware limitations. Not understanding these
extensions could lead to encrypting with the wrong protocol and
violating security assumptions.
2026-04-08 04:12:35 +01:00
Jack Grigg ca1cd587ff Merge pull request #184 from str4d/release-0.5.0
Publish release binaries / Publish for macos-arm64 (push) Has been cancelled
Publish release binaries / Publish for macos-x86_64 (push) Has been cancelled
Publish release binaries / Publish for linux (push) Has been cancelled
Publish release binaries / Publish for windows (push) Has been cancelled
Publish release binaries / Debian linux (push) Has been cancelled
Release 0.5.0
2024-08-04 04:29:40 +01:00
Jack Grigg 0699991f2b v0.5.0 2024-08-04 03:17:15 +00:00
Jack Grigg 76143524ef cargo update 2024-08-04 03:16:48 +00:00
Jack Grigg fec9dcc994 Merge pull request #183 from str4d/update-deps-0.5.0
Update dependencies for 0.5.0
2024-08-04 02:58:41 +01:00
Jack Grigg 8aeb9f3da7 CI: Test on both MSRV and latest stable 2024-07-30 05:54:36 +00:00
Jack Grigg 34011088a0 Fix 1.67 clippy lints 2024-07-30 05:42:54 +00:00
Jack Grigg 24e6e6ffa6 which 5, test-with 0.11 2024-07-30 05:36:19 +00:00
Jack Grigg a44859d6b2 sysinfo 0.29 2024-07-30 05:33:42 +00:00
Jack Grigg 4921cbf6ed i18n-embed 0.14 2024-07-30 05:31:19 +00:00
Jack Grigg d6729e99ba dialoguer 0.11 2024-07-30 05:27:06 +00:00
Jack Grigg 6452fa0540 age-plugin 0.5 2024-07-30 05:19:27 +00:00
Jack Grigg 71eb71d9c6 cargo update 2024-07-30 05:19:23 +00:00
Jack Grigg f0d82245ea time 0.3.36
Closes str4d/age-plugin-yubikey#182.
2024-07-30 05:19:23 +00:00
Jack Grigg c7e6fdf58a Bump MSRV to 1.67
`time 0.3.35` has MSRV 1.67, and is a required update in order to fix
breakage on Rust 1.80 and above.
2024-07-30 05:05:09 +00:00
Jack Grigg 4a44fb9025 CI: Migrate to codecov-action@4.5.0 2024-07-30 04:59:00 +00:00
Jack Grigg c4256dddba CI: Migrate to cargo-tarpaulin container for code coverage 2024-07-30 04:56:43 +00:00
str4d 5159577135 Merge pull request #163 from str4d/dependabot/github_actions/codecov/codecov-action-3.1.5
Bump codecov/codecov-action from 3.1.1 to 3.1.5
2024-01-28 06:38:11 +00:00
dependabot[bot] e0b944a524 Bump codecov/codecov-action from 3.1.1 to 3.1.5
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.1 to 3.1.5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3.1.1...v3.1.5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-28 05:07:06 +00:00
str4d eadebfa2f6 Merge pull request #162 from str4d/ci-updates
CI updates
2024-01-28 05:06:21 +00:00
Jack Grigg 137df751fe CI: Fix test job 2024-01-28 04:21:51 +00:00
Jack Grigg a24de089e0 CI: Remove pointless timeouts 2024-01-28 04:21:44 +00:00
Jack Grigg 982b9d2f95 CI: actions/checkout@v4 2024-01-28 04:21:44 +00:00
str4d 0ebbc31890 Merge pull request #161 from str4d/packages
Add entries for existing packages to README
2024-01-28 03:58:20 +00:00
Jack Grigg d373d531e5 Add entries for existing packages to README 2024-01-28 03:45:04 +00:00
str4d 72da2b46c7 Merge pull request #149 from str4d/dependabot/github_actions/svenstaro/upload-release-action-2.6.1
Bump svenstaro/upload-release-action from 2.5.0 to 2.6.1
2024-01-28 03:32:14 +00:00
str4d d31c60f733 Merge pull request #158 from robinp/patch-1
Add Arch linux notes
2024-01-22 20:02:51 +00:00
str4d d7d47e861d Merge pull request #151 from pierreprinetti/readme_fedora
Add installation instructions for Fedora Linux
2024-01-22 20:02:20 +00:00
Robin Palotai 9bb39a7b95 Add Arch linux notes
I had `pcscd` already installed, but age-plugin-yubikey didn't work initially.

I installed `pcsc-tools` so I could do `pcsc_scan`, which also found nothing. Then I installed `yubikey-manager` so I could `ykman info`, which worked, but after that magically pcsc_scan and age-plugin-yubikey were working too.

Not sure if installing `yubikey-manager` had to do with it, but anyway.
2023-12-21 14:54:08 +01:00
Pierre Prinetti 7c512d283c Add installation instructions for Fedora Linux
Add entries in the README to get the PC/SC dependency ready under
Fedora.
2023-06-21 16:25:36 +02:00
dependabot[bot] 351d40e0c7 Bump svenstaro/upload-release-action from 2.5.0 to 2.6.1
Bumps [svenstaro/upload-release-action](https://github.com/svenstaro/upload-release-action) from 2.5.0 to 2.6.1.
- [Release notes](https://github.com/svenstaro/upload-release-action/releases)
- [Changelog](https://github.com/svenstaro/upload-release-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/svenstaro/upload-release-action/compare/2.5.0...2.6.1)

---
updated-dependencies:
- dependency-name: svenstaro/upload-release-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-01 09:01:22 +00:00
str4d acc783d0d3 Merge pull request #142 from str4d/update-release-workflow
Update release workflow
2023-04-09 10:34:52 +01:00
Jack Grigg 379adcb909 Update release workflow
- `ubuntu-18.04` runner has been deprecated and removed by GitHub. We
  now use `ubuntu-20.04`.
- `actions-rs/toolchain` is replaced by `dtolnay/rust-toolchain`.
2023-04-09 09:16:42 +00:00
15 changed files with 942 additions and 745 deletions
+65 -17
View File
@@ -1,10 +1,13 @@
name: CI checks name: CI checks
on: [push, pull_request] on:
pull_request:
push:
branches: main
jobs: jobs:
test: test-msrv:
name: Test on ${{ matrix.name }} name: Test MSRV on ${{ matrix.name }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
@@ -22,37 +25,83 @@ jobs:
os: macos-latest os: macos-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install build dependencies - name: Install build dependencies
run: sudo apt install ${{ matrix.build_deps }} run: sudo apt install ${{ matrix.build_deps }}
if: matrix.build_deps != '' if: matrix.build_deps != ''
- uses: dtolnay/rust-toolchain@stable
id: stable-toolchain
- name: Install test dependencies using latest stable Rust
run: cargo +${{steps.stable-toolchain.outputs.name}} install rage
- name: Run tests
run: cargo test
- name: Verify working directory is clean
run: git diff --exit-code
test-latest:
name: Test latest stable on ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
name: [linux, windows, macos]
include:
- name: linux
os: ubuntu-latest
build_deps: >
libpcsclite-dev
- name: windows
os: windows-latest
- name: macos
os: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install build dependencies
run: sudo apt install ${{ matrix.build_deps }}
if: matrix.build_deps != ''
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/rust-toolchain@stable
id: toolchain
- run: rustup override set ${{steps.toolchain.outputs.name}}
- name: Install test dependencies - name: Install test dependencies
run: cargo install rage run: cargo install rage
- run: cargo fetch - name: Remove lockfile to build with latest dependencies
- name: Build tests run: rm Cargo.lock
run: cargo build --verbose --tests
- name: Run tests - name: Run tests
run: cargo test --verbose run: cargo test
- name: Verify working directory is clean (excluding lockfile)
run: git diff --exit-code ':!Cargo.lock'
codecov: codecov:
name: Code coverage name: Code coverage
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: xd009642/tarpaulin:develop-nightly
options: --security-opt seccomp=unconfined
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install build dependencies - name: Install build dependencies
run: sudo apt install libpcsclite-dev run: apt update && apt install -y libpcsclite-dev
- name: Install coverage dependencies
run: cargo install cargo-tarpaulin
- name: Generate coverage report - name: Generate coverage report
run: cargo tarpaulin --engine llvm --all-features --release --timeout 600 --out Xml run: >
cargo tarpaulin
--engine llvm
--timeout 180
--out xml
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.1.1 uses: codecov/codecov-action@v4.5.0
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
doc-links: doc-links:
name: Intra-doc links name: Intra-doc links
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install build dependencies - name: Install build dependencies
run: sudo apt install libpcsclite-dev run: sudo apt install libpcsclite-dev
- run: cargo fetch - run: cargo fetch
@@ -62,9 +111,8 @@ jobs:
fmt: fmt:
name: Rustfmt name: Rustfmt
timeout-minutes: 30
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Check formatting - name: Check formatting
run: cargo fmt -- --check run: cargo fmt -- --check
+1 -2
View File
@@ -6,10 +6,9 @@ on: pull_request
jobs: jobs:
clippy-beta: clippy-beta:
name: Clippy (beta) name: Clippy (beta)
timeout-minutes: 30
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@beta - uses: dtolnay/rust-toolchain@beta
id: toolchain id: toolchain
- run: rustup override set ${{steps.toolchain.outputs.name}} - run: rustup override set ${{steps.toolchain.outputs.name}}
+1 -2
View File
@@ -6,10 +6,9 @@ on: pull_request
jobs: jobs:
clippy: clippy:
name: Clippy (MSRV) name: Clippy (MSRV)
timeout-minutes: 30
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install build dependencies - name: Install build dependencies
run: sudo apt install libpcsclite-dev run: sudo apt install libpcsclite-dev
- name: Run clippy - name: Run clippy
+12 -14
View File
@@ -24,7 +24,7 @@ jobs:
- windows - windows
include: include:
- name: linux - name: linux
os: ubuntu-18.04 os: ubuntu-20.04
build_deps: > build_deps: >
libpcsclite-dev libpcsclite-dev
archive_name: age-plugin-yubikey.tar.gz archive_name: age-plugin-yubikey.tar.gz
@@ -48,11 +48,10 @@ jobs:
asset_suffix: x86_64-darwin.tar.gz asset_suffix: x86_64-darwin.tar.gz
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1 - uses: dtolnay/rust-toolchain@stable
with: id: toolchain
toolchain: stable - run: rustup override set ${{steps.toolchain.outputs.name}}
override: true
- name: Add target - name: Add target
run: rustup target add ${{ matrix.target }} run: rustup target add ${{ matrix.target }}
if: matrix.target != '' if: matrix.target != ''
@@ -87,7 +86,7 @@ jobs:
if: matrix.name == 'windows' if: matrix.name == 'windows'
- name: Upload archive to release - name: Upload archive to release
uses: svenstaro/upload-release-action@2.5.0 uses: svenstaro/upload-release-action@2.6.1
with: with:
file: ${{ matrix.archive_name }} file: ${{ matrix.archive_name }}
asset_name: age-plugin-yubikey-$tag-${{ matrix.asset_suffix }} asset_name: age-plugin-yubikey-$tag-${{ matrix.asset_suffix }}
@@ -96,7 +95,7 @@ jobs:
deb: deb:
name: Debian ${{ matrix.name }} name: Debian ${{ matrix.name }}
runs-on: ubuntu-18.04 runs-on: ubuntu-20.04
strategy: strategy:
matrix: matrix:
name: [linux] name: [linux]
@@ -107,11 +106,10 @@ jobs:
libpcsclite-dev libpcsclite-dev
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1 - uses: dtolnay/rust-toolchain@stable
with: id: toolchain
toolchain: stable - run: rustup override set ${{steps.toolchain.outputs.name}}
override: true
- name: Add target - name: Add target
run: rustup target add ${{ matrix.target }} run: rustup target add ${{ matrix.target }}
- name: cargo install cargo-deb - name: cargo install cargo-deb
@@ -146,7 +144,7 @@ jobs:
args: --package age-plugin-yubikey --no-build --target ${{ matrix.target }} args: --package age-plugin-yubikey --no-build --target ${{ matrix.target }}
- name: Upload Debian package to release - name: Upload Debian package to release
uses: svenstaro/upload-release-action@2.5.0 uses: svenstaro/upload-release-action@2.6.1
with: with:
file: target/${{ matrix.target }}/debian/*.deb file: target/${{ matrix.target }}/debian/*.deb
file_glob: true file_glob: true
+13
View File
@@ -8,6 +8,19 @@ to 0.3.0 are beta releases.
## [Unreleased] ## [Unreleased]
## [0.3.4], [0.4.1], [0.5.1] - 2026-04-08
### Fixed
- `age-plugin-yubikey` now completely ignores any identity that has unrecognised
critical extensions in its certificate, to ensure it doesn't misuse a newer
identity type.
## [0.5.0] - 2024-08-04
### Fixed
- `age-plugin-yubikey` can now be compiled with Rust 1.80 and above.
### Changed
- MSRV is now 1.67.0.
## [0.4.0] - 2023-04-09 ## [0.4.0] - 2023-04-09
### Changed ### Changed
- MSRV is now 1.65.0. - MSRV is now 1.65.0.
Generated
+772 -670
View File
File diff suppressed because it is too large Load Diff
+12 -12
View File
@@ -1,7 +1,7 @@
[package] [package]
name = "age-plugin-yubikey" name = "age-plugin-yubikey"
description = "YubiKey plugin for age clients" description = "YubiKey plugin for age clients"
version = "0.4.0" version = "0.5.1"
authors = ["Jack Grigg <thestr4d@gmail.com>"] authors = ["Jack Grigg <thestr4d@gmail.com>"]
repository = "https://github.com/str4d/age-plugin-yubikey" repository = "https://github.com/str4d/age-plugin-yubikey"
readme = "README.md" readme = "README.md"
@@ -9,7 +9,7 @@ keywords = ["age", "cli", "encryption", "yubikey"]
categories = ["command-line-utilities", "cryptography"] categories = ["command-line-utilities", "cryptography"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
edition = "2021" edition = "2021"
rust-version = "1.65" # MSRV rust-version = "1.67" # MSRV
[package.metadata.deb] [package.metadata.deb]
extended-description = """\ extended-description = """\
@@ -22,12 +22,12 @@ assets = [
] ]
[dependencies] [dependencies]
age-core = "0.9" age-core = "0.10"
age-plugin = "0.4" age-plugin = "0.5"
base64 = "0.21" base64 = "0.21"
bech32 = "0.9" bech32 = "0.9"
console = { version = "0.15", default-features = false } console = { version = "0.15", default-features = false }
dialoguer = { version = "0.10", default-features = false, features = ["password"] } dialoguer = { version = "0.11", default-features = false, features = ["password"] }
env_logger = "0.10" env_logger = "0.10"
gumdrop = "0.8" gumdrop = "0.8"
hex = "0.4" hex = "0.4"
@@ -36,23 +36,23 @@ p256 = { version = "0.13", features = ["ecdh"] }
pcsc = "2.4" pcsc = "2.4"
rand = "0.8" rand = "0.8"
sha2 = "0.10" sha2 = "0.10"
which = "4.1" which = "5"
x509 = "0.2" x509 = "0.2"
x509-parser = "0.14" x509-parser = "0.14"
yubikey = { version = "=0.8.0-pre.0", features = ["untested"] } yubikey = { version = "=0.8.0-pre.0", features = ["untested"] }
# Translations # Translations
i18n-embed = { version = "0.13", features = ["desktop-requester", "fluent-system"] } i18n-embed = { version = "0.14", features = ["desktop-requester", "fluent-system"] }
i18n-embed-fl = "0.6" i18n-embed-fl = "0.8"
lazy_static = "1" lazy_static = "1"
rust-embed = "6" rust-embed = "8"
# GnuPG coexistence # GnuPG coexistence
sysinfo = "0.28" sysinfo = "0.29"
[dev-dependencies] [dev-dependencies]
flate2 = "1" flate2 = "1"
man = "0.3" man = "0.3"
tempfile = "3" tempfile = "3"
test-with = "0.9" test-with = "0.11"
which = "4" which = "5"
+9 -1
View File
@@ -8,8 +8,13 @@ which enables files to be encrypted to age identities stored on YubiKeys.
| Environment | CLI command | | Environment | CLI command |
|-------------|-------------| |-------------|-------------|
| Cargo (Rust 1.65+) | `cargo install age-plugin-yubikey` | | Cargo (Rust 1.67+) | `cargo install age-plugin-yubikey` |
| Homebrew (macOS or Linux) | `brew install age-plugin-yubikey` | | Homebrew (macOS or Linux) | `brew install age-plugin-yubikey` |
| Arch Linux | `pacman -S age-plugin-yubikey` |
| Debian | [Debian package](https://github.com/str4d/age-plugin-yubikey/releases) |
| NixOS | Add to config:<br>`environment.systemPackages = [`<br>` pkgs.age-plugin-yubikey`<br>`];`<br>Or run `nix-env -i age-plugin-yubikey` |
| Ubuntu 20.04+ | [Debian package](https://github.com/str4d/age-plugin-yubikey/releases) |
| OpenBSD | `pkg_add age-plugin-yubikey` (security/age-plugin-yubikey) |
On Windows, Linux, and macOS, you can use the On Windows, Linux, and macOS, you can use the
[pre-built binaries](https://github.com/str4d/age-plugin-yubikey/releases). [pre-built binaries](https://github.com/str4d/age-plugin-yubikey/releases).
@@ -24,8 +29,10 @@ is installed and running.
| Environment | CLI command | | Environment | CLI command |
|-------------|-------------| |-------------|-------------|
| Debian or Ubuntu | `sudo apt-get install pcscd` | | Debian or Ubuntu | `sudo apt-get install pcscd` |
| Fedora | `sudo dnf install pcsc-lite` |
| OpenBSD | As ```root``` do:<br>`pkg_add pcsc-lite ccid`<br>`rcctl enable pcscd`<br>`rcctl start pcscd` | | OpenBSD | As ```root``` do:<br>`pkg_add pcsc-lite ccid`<br>`rcctl enable pcscd`<br>`rcctl start pcscd` |
| FreeBSD | As ```root``` do:<br>`pkg install pcsc-lite libccid`<br>`service pcscd enable`<br>`service pcscd start` | | FreeBSD | As ```root``` do:<br>`pkg install pcsc-lite libccid`<br>`service pcscd enable`<br>`service pcscd start` |
| Arch | `sudo pacman -S pcsclite pcsc-tools yubikey-manager`<br>`sudo systemctl enable pcscd`<br>`sudo systemctl start pcscd`|
When installing via Cargo, you also need to ensure that the development headers When installing via Cargo, you also need to ensure that the development headers
for the `pcsc-lite` library are available, so that the `pcsc-sys` crate can be for the `pcsc-lite` library are available, so that the `pcsc-sys` crate can be
@@ -34,6 +41,7 @@ compiled.
| Environment | CLI command | | Environment | CLI command |
|-------------|-------------| |-------------|-------------|
| Debian or Ubuntu | `sudo apt-get install libpcsclite-dev` | | Debian or Ubuntu | `sudo apt-get install libpcsclite-dev` |
| Fedora | `sudo dnf install pcsc-lite-devel` |
### Windows Subsystem for Linux (WSL) ### Windows Subsystem for Linux (WSL)
+1 -1
View File
@@ -6,7 +6,7 @@ use std::io::prelude::*;
const MANPAGES_DIR: &str = "./target/manpages"; const MANPAGES_DIR: &str = "./target/manpages";
fn generate_manpage(page: String, name: &str) { fn generate_manpage(page: String, name: &str) {
let file = File::create(format!("{}/{}.1.gz", MANPAGES_DIR, name)) let file = File::create(format!("{MANPAGES_DIR}/{name}.1.gz"))
.expect("Should be able to open file in target directory"); .expect("Should be able to open file in target directory");
let mut encoder = GzEncoder::new(file, Compression::best()); let mut encoder = GzEncoder::new(file, Compression::best());
encoder encoder
+1
View File
@@ -204,6 +204,7 @@ err-invalid-flag-tui = Flag '{$flag}' cannot be used with the interactive in
err-invalid-pin-policy = Invalid PIN policy '{$policy}' (expected [{$expected}]). err-invalid-pin-policy = Invalid PIN policy '{$policy}' (expected [{$expected}]).
err-invalid-slot = Invalid slot '{$slot}' (expected number between 1 and 20). err-invalid-slot = Invalid slot '{$slot}' (expected number between 1 and 20).
err-invalid-touch-policy = Invalid touch policy '{$policy}' (expected [{$expected}]). err-invalid-touch-policy = Invalid touch policy '{$policy}' (expected [{$expected}]).
err-io-user = Failed to get input from user: {$err}
err-io = Failed to set up {-yubikey}: {$err} err-io = Failed to set up {-yubikey}: {$err}
err-multiple-commands = Only one of {-cmd-generate}, {-cmd-identity}, {-cmd-list}, {-cmd-list-all} can be specified. err-multiple-commands = Only one of {-cmd-generate}, {-cmd-identity}, {-cmd-list}, {-cmd-list-all} can be specified.
err-multiple-yubikeys = Multiple {-yubikeys} are plugged in. Use {-flag-serial} to select a single {-yubikey}. err-multiple-yubikeys = Multiple {-yubikeys} are plugged in. Use {-flag-serial} to select a single {-yubikey}.
+1 -1
View File
@@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "1.65.0" channel = "1.67.0"
components = ["clippy", "rustfmt"] components = ["clippy", "rustfmt"]
+8
View File
@@ -15,6 +15,7 @@ macro_rules! wlnfl {
pub enum Error { pub enum Error {
CustomManagementKey, CustomManagementKey,
Dialog(dialoguer::Error),
InvalidFlagCommand(String, String), InvalidFlagCommand(String, String),
InvalidFlagTui(String), InvalidFlagTui(String),
InvalidPinPolicy(String), InvalidPinPolicy(String),
@@ -35,6 +36,12 @@ pub enum Error {
YubiKey(yubikey::Error), YubiKey(yubikey::Error),
} }
impl From<dialoguer::Error> for Error {
fn from(e: dialoguer::Error) -> Self {
Error::Dialog(e)
}
}
impl From<io::Error> for Error { impl From<io::Error> for Error {
fn from(e: io::Error) -> Self { fn from(e: io::Error) -> Self {
Error::Io(e) Error::Io(e)
@@ -65,6 +72,7 @@ impl fmt::Debug for Error {
url = CHANGE_MGMT_KEY_URL url = CHANGE_MGMT_KEY_URL
)?; )?;
} }
Error::Dialog(e) => wlnfl!(f, "err-io-user", err = e.to_string())?,
Error::InvalidFlagCommand(flag, command) => wlnfl!( Error::InvalidFlagCommand(flag, command) => wlnfl!(
f, f,
"err-invalid-flag-command", "err-invalid-flag-command",
+37 -10
View File
@@ -15,6 +15,7 @@ use std::io;
use std::iter; use std::iter;
use std::thread::sleep; use std::thread::sleep;
use std::time::{Duration, Instant, SystemTime}; use std::time::{Duration, Instant, SystemTime};
use x509_parser::der_parser::oid::Oid;
use yubikey::{ use yubikey::{
certificate::Certificate, certificate::Certificate,
piv::{decrypt_data, AlgorithmId, RetiredSlotId, SlotId}, piv::{decrypt_data, AlgorithmId, RetiredSlotId, SlotId},
@@ -27,13 +28,16 @@ use crate::{
fl, fl,
format::{RecipientLine, STANZA_KEY_LABEL}, format::{RecipientLine, STANZA_KEY_LABEL},
p256::{Recipient, TAG_BYTES}, p256::{Recipient, TAG_BYTES},
util::{otp_serial_prefix, Metadata}, util::{otp_serial_prefix, Metadata, POLICY_EXTENSION_OID},
IDENTITY_PREFIX, IDENTITY_PREFIX,
}; };
const ONE_SECOND: Duration = Duration::from_secs(1); const ONE_SECOND: Duration = Duration::from_secs(1);
const FIFTEEN_SECONDS: Duration = Duration::from_secs(15); const FIFTEEN_SECONDS: Duration = Duration::from_secs(15);
/// The set of OIDs that we understand and use when parsing YubiKey slot certificates.
const KNOWN_OIDS: &[&[u64]] = &[POLICY_EXTENSION_OID];
pub(crate) fn is_connected(reader: Reader) -> bool { pub(crate) fn is_connected(reader: Reader) -> bool {
filter_connected(&reader) filter_connected(&reader)
} }
@@ -274,10 +278,10 @@ pub(crate) fn disconnect_without_reset(yubikey: YubiKey) {
let _ = yubikey.disconnect(pcsc::Disposition::LeaveCard); let _ = yubikey.disconnect(pcsc::Disposition::LeaveCard);
} }
fn request_pin<E>( fn request_pin<E, E2>(
mut prompt: impl FnMut(Option<String>) -> io::Result<Result<SecretString, E>>, mut prompt: impl FnMut(Option<String>) -> Result<Result<SecretString, E>, E2>,
serial: Serial, serial: Serial,
) -> io::Result<Result<SecretString, E>> { ) -> Result<Result<SecretString, E>, E2> {
let mut prev_error = None; let mut prev_error = None;
loop { loop {
prev_error = Some(match prompt(prev_error)? { prev_error = Some(match prompt(prev_error)? {
@@ -326,7 +330,7 @@ pub(crate) fn manage(yubikey: &mut YubiKey) -> Result<(), Error> {
let pin = request_pin( let pin = request_pin(
|prev_error| { |prev_error| {
if let Some(err) = prev_error { if let Some(err) = prev_error {
eprintln!("{}", err); eprintln!("{err}");
} }
Password::new() Password::new()
.with_prompt(fl!("mgr-choose-new-pin")) .with_prompt(fl!("mgr-choose-new-pin"))
@@ -388,6 +392,30 @@ pub(crate) fn manage(yubikey: &mut YubiKey) -> Result<(), Error> {
Ok(()) Ok(())
} }
/// Parses the certificate to identify the preferred recipient type it corresponds to.
pub(crate) fn identify_recipient(cert: &Certificate) -> Option<Recipient> {
let known_oids = KNOWN_OIDS
.iter()
.map(|oid| Oid::from(oid).unwrap())
.collect::<Vec<_>>();
// If the certificate contains any unrecognised critical extensions, reject it: we
// don't know how to correctly use the identity. In particular, some identities store
// parts of their private key material in certificate extensions to work around
// hardware limitations. Not understanding these extensions could lead to encrypting
// with the wrong protocol and violating security assumptions.
let (_, c) = x509_parser::parse_x509_certificate(cert.as_ref()).ok()?;
if c.tbs_certificate
.extensions()
.iter()
.any(|ext| ext.critical && !known_oids.contains(&ext.oid))
{
return None;
}
Recipient::from_certificate(cert)
}
/// Returns an iterator of keys that are occupying plugin-compatible slots, along with the /// Returns an iterator of keys that are occupying plugin-compatible slots, along with the
/// corresponding recipient if the key is compatible with this plugin. /// corresponding recipient if the key is compatible with this plugin.
pub(crate) fn list_slots( pub(crate) fn list_slots(
@@ -397,8 +425,7 @@ pub(crate) fn list_slots(
// We only use the retired slots. // We only use the retired slots.
match key.slot() { match key.slot() {
SlotId::Retired(slot) => { SlotId::Retired(slot) => {
// Only P-256 keys are compatible with us. let recipient = identify_recipient(key.certificate());
let recipient = Recipient::from_certificate(key.certificate());
Some((key, slot, recipient)) Some((key, slot, recipient))
} }
_ => None, _ => None,
@@ -605,9 +632,9 @@ impl Stub {
let (cert, pk) = match Certificate::read(&mut yubikey, SlotId::Retired(self.slot)) let (cert, pk) = match Certificate::read(&mut yubikey, SlotId::Retired(self.slot))
.ok() .ok()
.and_then(|cert| { .and_then(|cert| {
Recipient::from_certificate(&cert) identify_recipient(&cert)
.filter(|pk| pk.tag() == self.tag) .filter(|recipient| recipient.tag() == self.tag)
.map(|pk| (cert, pk)) .map(|r| (cert, r))
}) { }) {
Some(pk) => pk, Some(pk) => pk,
None => { None => {
+8 -14
View File
@@ -296,8 +296,8 @@ fn list(flags: PluginFlags, all: bool) -> Result<(), Error> {
flags, flags,
all, all,
|_, recipient, metadata| { |_, recipient, metadata| {
println!("{}", metadata); println!("{metadata}");
println!("{}", recipient); println!("{recipient}");
}, },
) )
} }
@@ -329,8 +329,8 @@ fn main() -> Result<(), Error> {
if let Some(state_machine) = opts.age_plugin { if let Some(state_machine) = opts.age_plugin {
run_state_machine( run_state_machine(
&state_machine, &state_machine,
plugin::RecipientPlugin::default, Some(plugin::RecipientPlugin::default),
plugin::IdentityPlugin::default, Some(plugin::IdentityPlugin::default),
)?; )?;
Ok(()) Ok(())
} else if opts.version { } else if opts.version {
@@ -411,9 +411,9 @@ fn main() -> Result<(), Error> {
.validity() .validity()
.not_before .not_before
.to_rfc2822() .to_rfc2822()
.unwrap_or_else(|e| format!("Invalid date: {}", e)); .unwrap_or_else(|e| format!("Invalid date: {e}"));
format!("{}, created: {}", name, created) format!("{name}, created: {created}")
}) })
}) })
}) })
@@ -631,14 +631,8 @@ fn main() -> Result<(), Error> {
// If `rage` binary is installed, use it in examples. Otherwise default to `age`. // If `rage` binary is installed, use it in examples. Otherwise default to `age`.
let age_binary = which::which("rage").map(|_| "rage").unwrap_or("age"); let age_binary = which::which("rage").map(|_| "rage").unwrap_or("age");
let encrypt_usage = format!( let encrypt_usage = format!("$ cat foo.txt | {age_binary} -r {recipient} -o foo.txt.age");
"$ cat foo.txt | {} -r {} -o foo.txt.age", let decrypt_usage = format!("$ cat foo.txt.age | {age_binary} -d -i {file_name} > foo.txt");
age_binary, recipient
);
let decrypt_usage = format!(
"$ cat foo.txt.age | {} -d -i {} > foo.txt",
age_binary, file_name
);
let identity_usage = format!( let identity_usage = format!(
"$ age-plugin-yubikey -i --serial {} --slot {} > {}", "$ age-plugin-yubikey -i --serial {} --slot {} > {}",
stub.serial, stub.serial,
+1 -1
View File
@@ -177,7 +177,7 @@ impl Metadata {
.validity() .validity()
.not_before .not_before
.to_rfc2822() .to_rfc2822()
.unwrap_or_else(|e| format!("Invalid date: {}", e)), .unwrap_or_else(|e| format!("Invalid date: {e}")),
pin_policy, pin_policy,
touch_policy, touch_policy,
}) })