32 Commits

Author SHA1 Message Date
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 907 additions and 776 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
+5 -4
View File
@@ -8,11 +8,12 @@ to 0.3.0 are beta releases.
## [Unreleased] ## [Unreleased]
## [0.3.4], [0.4.1] - 2026-04-08 ## [0.5.0] - 2024-08-04
### Fixed ### Fixed
- `age-plugin-yubikey` now completely ignores any identity that has unrecognised - `age-plugin-yubikey` can now be compiled with Rust 1.80 and above.
critical extensions in its certificate, to ensure it doesn't misuse a newer
identity type. ### Changed
- MSRV is now 1.67.0.
## [0.4.0] - 2023-04-09 ## [0.4.0] - 2023-04-09
### Changed ### Changed
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.1" version = "0.5.0"
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",
+10 -37
View File
@@ -15,7 +15,6 @@ 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},
@@ -28,16 +27,13 @@ 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, POLICY_EXTENSION_OID}, util::{otp_serial_prefix, Metadata},
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)
} }
@@ -278,10 +274,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)? {
@@ -330,7 +326,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"))
@@ -392,30 +388,6 @@ 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(
@@ -425,7 +397,8 @@ 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) => {
let recipient = identify_recipient(key.certificate()); // Only P-256 keys are compatible with us.
let recipient = Recipient::from_certificate(key.certificate());
Some((key, slot, recipient)) Some((key, slot, recipient))
} }
_ => None, _ => None,
@@ -632,9 +605,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| {
identify_recipient(&cert) Recipient::from_certificate(&cert)
.filter(|recipient| recipient.tag() == self.tag) .filter(|pk| pk.tag() == self.tag)
.map(|r| (cert, r)) .map(|pk| (cert, pk))
}) { }) {
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,
}) })