Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a36a37ae3 | |||
| 3463d109b2 | |||
| 014b7ee6fd | |||
| 498de4c10d | |||
| 98b038c873 | |||
| fab9d25b0a | |||
| bb80551324 | |||
| 9e20ecfe55 | |||
| fac83c60fb | |||
| 914f9bee0d | |||
| 83de59983f | |||
| e21395c934 | |||
| 935fea0868 | |||
| dd4b1c60a4 | |||
| 74a50f0f0c | |||
| 86d482b38d |
@@ -36,13 +36,13 @@ jobs:
|
|||||||
toolchain: stable
|
toolchain: stable
|
||||||
deps: true
|
deps: true
|
||||||
- platform: ubuntu-latest
|
- platform: ubuntu-latest
|
||||||
toolchain: 1.51.0 # MSRV
|
toolchain: 1.57.0 # MSRV
|
||||||
deps: sudo apt-get install libpcsclite-dev
|
deps: sudo apt-get install libpcsclite-dev
|
||||||
- platform: windows-latest
|
- platform: windows-latest
|
||||||
toolchain: 1.51.0 # MSRV
|
toolchain: 1.57.0 # MSRV
|
||||||
deps: true
|
deps: true
|
||||||
- platform: macos-latest
|
- platform: macos-latest
|
||||||
toolchain: 1.51.0 # MSRV
|
toolchain: 1.57.0 # MSRV
|
||||||
deps: true
|
deps: true
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
steps:
|
steps:
|
||||||
@@ -82,7 +82,7 @@ jobs:
|
|||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: 1.51.0 # MSRV
|
toolchain: 1.57.0 # MSRV
|
||||||
components: clippy
|
components: clippy
|
||||||
override: true
|
override: true
|
||||||
- run: sudo apt-get install libpcsclite-dev
|
- run: sudo apt-get install libpcsclite-dev
|
||||||
|
|||||||
@@ -4,6 +4,29 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## 0.6.0 (2022-08-10)
|
||||||
|
### Changed
|
||||||
|
- 2021 edition upgrade ([#343])
|
||||||
|
- RustCrypto crate upgrades; MSRV 1.57 ([#378])
|
||||||
|
- `des` v0.8
|
||||||
|
- `elliptic-curve` v0.12
|
||||||
|
- `hmac` v0.12
|
||||||
|
- `num-bigint-dig` v0.8
|
||||||
|
- `pbkdf2` v0.11
|
||||||
|
- `p256` v0.11
|
||||||
|
- `p384` v0.11
|
||||||
|
- `rsa` v0.6
|
||||||
|
- `sha1` v0.10 (replacing `sha-1`)
|
||||||
|
- `sha2` v0.10
|
||||||
|
- Bump `uuid` to v1.0 ([#376])
|
||||||
|
- Bump `der-parser` to v8.0 ([#402])
|
||||||
|
- Bump `x509-parser` to v0.14 ([#402])
|
||||||
|
|
||||||
|
[#343]: https://github.com/iqlusioninc/yubikey.rs/pull/343
|
||||||
|
[#376]: https://github.com/iqlusioninc/yubikey.rs/pull/376
|
||||||
|
[#378]: https://github.com/iqlusioninc/yubikey.rs/pull/378
|
||||||
|
[#402]: https://github.com/iqlusioninc/yubikey.rs/pull/402
|
||||||
|
|
||||||
## 0.5.0 (2021-11-21)
|
## 0.5.0 (2021-11-21)
|
||||||
### Changed
|
### Changed
|
||||||
- Update `rsa` dependency to 0.5 ([#315])
|
- Update `rsa` dependency to 0.5 ([#315])
|
||||||
|
|||||||
Generated
+668
-226
File diff suppressed because it is too large
Load Diff
+16
-15
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "yubikey"
|
name = "yubikey"
|
||||||
version = "0.5.0" # Also update html_root_url in lib.rs when bumping this
|
version = "0.6.0"
|
||||||
description = """
|
description = """
|
||||||
Pure Rust cross-platform host-side driver for YubiKey devices from Yubico with
|
Pure Rust cross-platform host-side driver for YubiKey devices from Yubico with
|
||||||
support for hardware-backed public-key decryption and digital signatures using
|
support for hardware-backed public-key decryption and digital signatures using
|
||||||
@@ -8,12 +8,13 @@ the Personal Identity Verification (PIV) application. Supports RSA (1024/2048)
|
|||||||
or ECC (NIST P-256/P-384) algorithms e.g, PKCS#1v1.5, ECDSA
|
or ECC (NIST P-256/P-384) algorithms e.g, PKCS#1v1.5, ECDSA
|
||||||
"""
|
"""
|
||||||
authors = ["Tony Arcieri <tony@iqlusion.io>", "Yubico AB"]
|
authors = ["Tony Arcieri <tony@iqlusion.io>", "Yubico AB"]
|
||||||
edition = "2018"
|
|
||||||
license = "BSD-2-Clause"
|
license = "BSD-2-Clause"
|
||||||
repository = "https://github.com/iqlusioninc/yubikey.rs"
|
repository = "https://github.com/iqlusioninc/yubikey.rs"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
categories = ["api-bindings", "cryptography", "hardware-support"]
|
categories = ["api-bindings", "cryptography", "hardware-support"]
|
||||||
keywords = ["ecdsa", "encryption", "rsa", "piv", "signature"]
|
keywords = ["ecdsa", "encryption", "rsa", "piv", "signature"]
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.57"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [".", "cli"]
|
members = [".", "cli"]
|
||||||
@@ -21,29 +22,29 @@ members = [".", "cli"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
cookie-factory = "0.3"
|
cookie-factory = "0.3"
|
||||||
der-parser = "6"
|
der-parser = "8"
|
||||||
des = "0.7"
|
des = "0.8"
|
||||||
elliptic-curve = "0.10"
|
elliptic-curve = "0.12"
|
||||||
hmac = "0.11"
|
hmac = "0.12"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
nom = "7"
|
nom = "7"
|
||||||
num-bigint-dig = { version = "0.7", features = ["rand"] }
|
num-bigint-dig = { version = "0.8", features = ["rand"] }
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
num-integer = "0.1"
|
num-integer = "0.1"
|
||||||
pbkdf2 = { version = "0.9", default-features = false }
|
pbkdf2 = { version = "0.11", default-features = false }
|
||||||
p256 = "0.9"
|
p256 = "0.11"
|
||||||
p384 = "0.8"
|
p384 = "0.11"
|
||||||
pcsc = "2"
|
pcsc = "2"
|
||||||
rand_core = { version = "0.6", features = ["std"] }
|
rand_core = { version = "0.6", features = ["std"] }
|
||||||
rsa = "0.5"
|
rsa = "0.6"
|
||||||
secrecy = "0.8"
|
secrecy = "0.8"
|
||||||
sha-1 = "0.9"
|
sha1 = "0.10"
|
||||||
sha2 = "0.9"
|
sha2 = "0.10"
|
||||||
subtle = "2"
|
subtle = "2"
|
||||||
subtle-encoding = "0.5"
|
subtle-encoding = "0.5"
|
||||||
uuid = { version = "0.8", features = ["v4"] }
|
uuid = { version = "1.0", features = ["v4"] }
|
||||||
x509 = "0.2"
|
x509 = "0.2"
|
||||||
x509-parser = "0.12"
|
x509-parser = "0.14"
|
||||||
zeroize = "1"
|
zeroize = "1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
[![crate][crate-image]][crate-link]
|
[![crate][crate-image]][crate-link]
|
||||||
[![Docs][docs-image]][docs-link]
|
[![Docs][docs-image]][docs-link]
|
||||||
[![2-Clause BSD Licensed][license-image]][license-link]
|
[![2-Clause BSD Licensed][license-image]][license-link]
|
||||||
![Rust Version][rustc-image]
|
![MSRV][msrv-image]
|
||||||
[![Safety Dance][safety-image]][safety-link]
|
[![Safety Dance][safety-image]][safety-link]
|
||||||
[![Build Status][build-image]][build-link]
|
[![Build Status][build-image]][build-link]
|
||||||
[![dependency status][deps-image]][deps-link]
|
[![dependency status][deps-image]][deps-link]
|
||||||
@@ -26,8 +26,8 @@ encryption (PKCS#1v1.5/ECIES) use cases are supported for either key type.
|
|||||||
See [Yubico's guide to PIV-enabled YubiKeys][yk-guide] for more information
|
See [Yubico's guide to PIV-enabled YubiKeys][yk-guide] for more information
|
||||||
on which devices support PIV and the available functionality.
|
on which devices support PIV and the available functionality.
|
||||||
|
|
||||||
If you've been wanting to use Rust to sign and/or encrypt stuff using a
|
If you've been wanting to use Rust to sign and/or encrypt data using a
|
||||||
private key generated and stored on a Yubikey (with option PIN-based access),
|
private key generated and stored on a YubiKey (with option PIN-based access),
|
||||||
this is the crate you've been after!
|
this is the crate you've been after!
|
||||||
|
|
||||||
Note that while this project started as a fork of a [Yubico] project,
|
Note that while this project started as a fork of a [Yubico] project,
|
||||||
@@ -36,7 +36,7 @@ endorsed by Yubico.
|
|||||||
|
|
||||||
## Minimum Supported Rust Version
|
## Minimum Supported Rust Version
|
||||||
|
|
||||||
Rust **1.51** or newer.
|
Rust **1.57** or newer.
|
||||||
|
|
||||||
## Supported YubiKeys
|
## Supported YubiKeys
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ or conditions.
|
|||||||
[docs-link]: https://docs.rs/yubikey/
|
[docs-link]: https://docs.rs/yubikey/
|
||||||
[license-image]: https://img.shields.io/badge/license-BSD-blue.svg
|
[license-image]: https://img.shields.io/badge/license-BSD-blue.svg
|
||||||
[license-link]: https://github.com/iqlusioninc/yubikey.rs/blob/main/COPYING
|
[license-link]: https://github.com/iqlusioninc/yubikey.rs/blob/main/COPYING
|
||||||
[rustc-image]: https://img.shields.io/badge/rustc-1.51+-blue.svg
|
[msrv-image]: https://img.shields.io/badge/rustc-1.57+-blue.svg
|
||||||
[safety-image]: https://img.shields.io/badge/unsafe-forbidden-success.svg
|
[safety-image]: https://img.shields.io/badge/unsafe-forbidden-success.svg
|
||||||
[safety-link]: https://github.com/rust-secure-code/safety-dance/
|
[safety-link]: https://github.com/rust-secure-code/safety-dance/
|
||||||
[build-image]: https://github.com/iqlusioninc/yubikey.rs/workflows/CI/badge.svg?branch=main&event=push
|
[build-image]: https://github.com/iqlusioninc/yubikey.rs/workflows/CI/badge.svg?branch=main&event=push
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## 0.5.0 (2021-11-21)
|
||||||
|
### Changed
|
||||||
|
- Bump `yubikey` dependency to v0.5 ([#327])
|
||||||
|
|
||||||
|
[#327]: https://github.com/iqlusioninc/yubikey.rs/pull/327
|
||||||
|
|
||||||
## 0.4.0 (2021-07-12)
|
## 0.4.0 (2021-07-12)
|
||||||
### Changed
|
### Changed
|
||||||
- Switch to renamed `yubikey` crate ([#283])
|
- Switch to renamed `yubikey` crate ([#283])
|
||||||
|
|||||||
+5
-4
@@ -1,20 +1,21 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "yubikey-cli"
|
name = "yubikey-cli"
|
||||||
version = "0.5.0-pre"
|
version = "0.6.0-pre"
|
||||||
description = """
|
description = """
|
||||||
Command-line interface for performing encryption and signing using RSA/ECC keys
|
Command-line interface for performing encryption and signing using RSA/ECC keys
|
||||||
stored on YubiKey devices.
|
stored on YubiKey devices.
|
||||||
"""
|
"""
|
||||||
authors = ["Tony Arcieri <tony@iqlusion.io>"]
|
authors = ["Tony Arcieri <tony@iqlusion.io>"]
|
||||||
edition = "2018"
|
|
||||||
license = "BSD-2-Clause"
|
license = "BSD-2-Clause"
|
||||||
repository = "https://github.com/iqlusioninc/yubikey.rs"
|
repository = "https://github.com/iqlusioninc/yubikey.rs"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
categories = ["command-line-utilities", "cryptography", "hardware-support"]
|
categories = ["command-line-utilities", "cryptography", "hardware-support"]
|
||||||
keywords = ["ecdsa", "rsa", "piv", "pcsc", "yubikey"]
|
keywords = ["ecdsa", "rsa", "piv", "pcsc", "yubikey"]
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.56"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gumdrop = "0.8"
|
clap = { version = "3", features = ["derive"] }
|
||||||
env_logger = "0.9"
|
env_logger = "0.9"
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
@@ -22,4 +23,4 @@ sha2 = "0.9"
|
|||||||
subtle-encoding = "0.5"
|
subtle-encoding = "0.5"
|
||||||
termcolor = "1"
|
termcolor = "1"
|
||||||
x509-parser = "0.12"
|
x509-parser = "0.12"
|
||||||
yubikey = { version = "0.5", path = ".." }
|
yubikey = { version = "0.6", path = ".." }
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
unused_qualifications
|
unused_qualifications
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use gumdrop::Options;
|
use clap::Parser;
|
||||||
use yubikey_cli::commands::YubiKeyCli;
|
use yubikey_cli::commands::YubiKeyCli;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
YubiKeyCli::parse_args_default_or_exit().run();
|
YubiKeyCli::parse().run()
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-80
@@ -4,62 +4,25 @@ pub mod readers;
|
|||||||
pub mod status;
|
pub mod status;
|
||||||
|
|
||||||
use self::{readers::ReadersCmd, status::StatusCmd};
|
use self::{readers::ReadersCmd, status::StatusCmd};
|
||||||
use crate::terminal::{self, STDOUT};
|
use crate::terminal;
|
||||||
use gumdrop::Options;
|
use clap::Parser;
|
||||||
use std::{
|
use std::{env, process::exit};
|
||||||
env,
|
use termcolor::ColorChoice;
|
||||||
io::{self, Write},
|
|
||||||
process::exit,
|
|
||||||
};
|
|
||||||
use termcolor::{ColorChoice, ColorSpec, WriteColor};
|
|
||||||
use yubikey::{Serial, YubiKey};
|
use yubikey::{Serial, YubiKey};
|
||||||
|
|
||||||
/// The `yubikey` CLI utility
|
/// The `yubikey` CLI utility
|
||||||
#[derive(Debug, Options)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct YubiKeyCli {
|
pub struct YubiKeyCli {
|
||||||
/// Obtain help about the current command
|
/// Serial number of the YubiKey to connect to
|
||||||
#[options(short = "h", help = "print help message")]
|
#[clap(short = 's', long = "serial")]
|
||||||
pub help: bool,
|
|
||||||
|
|
||||||
/// Specify the serial number of the YubiKey to connect to
|
|
||||||
#[options(
|
|
||||||
short = "s",
|
|
||||||
long = "serial",
|
|
||||||
help = "serial number of the YubiKey to connect to"
|
|
||||||
)]
|
|
||||||
pub serial: Option<Serial>,
|
pub serial: Option<Serial>,
|
||||||
|
|
||||||
/// Subcommand to execute.
|
/// Subcommand to execute.
|
||||||
#[options(command)]
|
#[clap(subcommand)]
|
||||||
pub command: Option<Commands>,
|
pub command: Commands,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl YubiKeyCli {
|
impl YubiKeyCli {
|
||||||
/// Print usage information
|
|
||||||
pub fn print_usage() -> io::Result<()> {
|
|
||||||
let mut stdout = STDOUT.lock();
|
|
||||||
stdout.reset()?;
|
|
||||||
|
|
||||||
let mut bold = ColorSpec::new();
|
|
||||||
bold.set_bold(true);
|
|
||||||
|
|
||||||
stdout.set_color(&bold)?;
|
|
||||||
writeln!(
|
|
||||||
stdout,
|
|
||||||
"{} {}",
|
|
||||||
env!("CARGO_PKG_NAME"),
|
|
||||||
env!("CARGO_PKG_VERSION")
|
|
||||||
)?;
|
|
||||||
stdout.reset()?;
|
|
||||||
|
|
||||||
writeln!(stdout, "{}", env!("CARGO_PKG_AUTHORS"))?;
|
|
||||||
writeln!(stdout, "{}", env!("CARGO_PKG_DESCRIPTION").trim())?;
|
|
||||||
writeln!(stdout)?;
|
|
||||||
writeln!(stdout, "{}", Commands::usage())?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run the underlying command type or print usage info and exit
|
/// Run the underlying command type or print usage info and exit
|
||||||
pub fn run(&self) {
|
pub fn run(&self) {
|
||||||
// TODO(tarcieri): make this more configurable
|
// TODO(tarcieri): make this more configurable
|
||||||
@@ -70,10 +33,7 @@ impl YubiKeyCli {
|
|||||||
env_logger::builder().format_timestamp(None).init();
|
env_logger::builder().format_timestamp(None).init();
|
||||||
}
|
}
|
||||||
|
|
||||||
match &self.command {
|
self.command.run(self.yubikey_init())
|
||||||
Some(cmd) => cmd.run(self.yubikey_init()),
|
|
||||||
None => Self::print_usage().unwrap(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the YubiKey client driver
|
/// Initialize the YubiKey client driver
|
||||||
@@ -92,22 +52,18 @@ impl YubiKeyCli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Subcommands of this application
|
/// Subcommands of this application
|
||||||
#[derive(Debug, Options)]
|
#[derive(Debug, Parser)]
|
||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
/// `help` subcommand
|
|
||||||
#[options(help = "show help for a command")]
|
|
||||||
Help(HelpOpts),
|
|
||||||
|
|
||||||
/// `version` subcommand
|
/// `version` subcommand
|
||||||
#[options(help = "display version information")]
|
#[clap(about = "display version information")]
|
||||||
Version(VersionOpts),
|
Version(VersionOpts),
|
||||||
|
|
||||||
/// `readers` subcommand
|
/// `readers` subcommand
|
||||||
#[options(help = "list detected readers")]
|
#[clap(about = "list detected readers")]
|
||||||
Readers(ReadersCmd),
|
Readers(ReadersCmd),
|
||||||
|
|
||||||
/// `status` subcommand
|
/// `status` subcommand
|
||||||
#[options(help = "show yubikey status")]
|
#[clap(about = "show yubikey status")]
|
||||||
Status(StatusCmd),
|
Status(StatusCmd),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +71,6 @@ impl Commands {
|
|||||||
/// Run the given command
|
/// Run the given command
|
||||||
pub fn run(&self, yubikey: YubiKey) {
|
pub fn run(&self, yubikey: YubiKey) {
|
||||||
match self {
|
match self {
|
||||||
Commands::Help(help) => help.run(),
|
|
||||||
Commands::Version(version) => version.run(),
|
Commands::Version(version) => version.run(),
|
||||||
Commands::Readers(list) => list.run(),
|
Commands::Readers(list) => list.run(),
|
||||||
Commands::Status(status) => status.run(yubikey),
|
Commands::Status(status) => status.run(yubikey),
|
||||||
@@ -123,28 +78,8 @@ impl Commands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Help options
|
|
||||||
#[derive(Debug, Options)]
|
|
||||||
pub struct HelpOpts {
|
|
||||||
#[options(free, help = "subcommand to get help for")]
|
|
||||||
free: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HelpOpts {
|
|
||||||
fn run(&self) {
|
|
||||||
if let Some(command) = self.free.first() {
|
|
||||||
if let Some(usage) = Commands::command_usage(command) {
|
|
||||||
println!("{}", usage);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("{}", Commands::usage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Version options
|
/// Version options
|
||||||
#[derive(Debug, Options)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct VersionOpts {}
|
pub struct VersionOpts {}
|
||||||
|
|
||||||
impl VersionOpts {
|
impl VersionOpts {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! List detected readers
|
//! List detected readers
|
||||||
|
|
||||||
use crate::terminal::STDOUT;
|
use crate::terminal::STDOUT;
|
||||||
use gumdrop::Options;
|
use clap::Parser;
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
process::exit,
|
process::exit,
|
||||||
@@ -10,7 +10,7 @@ use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
|
|||||||
use yubikey::{Context, Serial};
|
use yubikey::{Context, Serial};
|
||||||
|
|
||||||
/// The `readers` subcommand
|
/// The `readers` subcommand
|
||||||
#[derive(Debug, Options)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct ReadersCmd {}
|
pub struct ReadersCmd {}
|
||||||
|
|
||||||
impl ReadersCmd {
|
impl ReadersCmd {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Print device status
|
//! Print device status
|
||||||
|
|
||||||
use crate::terminal::{print_cert_info, STDOUT};
|
use crate::terminal::{print_cert_info, STDOUT};
|
||||||
use gumdrop::Options;
|
use clap::Parser;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
|
use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
|
||||||
use yubikey::{piv::*, YubiKey};
|
use yubikey::{piv::*, YubiKey};
|
||||||
@@ -10,7 +10,7 @@ use yubikey::{piv::*, YubiKey};
|
|||||||
const NONE_STR: &str = "<none>";
|
const NONE_STR: &str = "<none>";
|
||||||
|
|
||||||
/// The `status` subcommand
|
/// The `status` subcommand
|
||||||
#[derive(Debug, Options)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct StatusCmd {}
|
pub struct StatusCmd {}
|
||||||
|
|
||||||
impl StatusCmd {
|
impl StatusCmd {
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
use crate::{Error, Result, YubiKey};
|
use crate::{Error, Result, YubiKey};
|
||||||
use rand_core::{OsRng, RngCore};
|
use rand_core::{OsRng, RngCore};
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryInto,
|
|
||||||
fmt::{self, Debug, Display},
|
fmt::{self, Debug, Display},
|
||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
|||||||
+12
-12
@@ -47,9 +47,7 @@ use p256::NistP256;
|
|||||||
use p384::NistP384;
|
use p384::NistP384;
|
||||||
use rsa::{PublicKeyParts, RsaPublicKey};
|
use rsa::{PublicKeyParts, RsaPublicKey};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::convert::TryFrom;
|
use std::{fmt, ops::DerefMut};
|
||||||
use std::fmt;
|
|
||||||
use std::ops::DerefMut;
|
|
||||||
use x509::{der::Oid, RelativeDistinguishedName};
|
use x509::{der::Oid, RelativeDistinguishedName};
|
||||||
use x509_parser::{parse_x509_certificate, x509::SubjectPublicKeyInfo};
|
use x509_parser::{parse_x509_certificate, x509::SubjectPublicKeyInfo};
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
@@ -85,7 +83,7 @@ impl TryFrom<&[u8]> for Serial {
|
|||||||
|
|
||||||
fn try_from(bytes: &[u8]) -> Result<Serial> {
|
fn try_from(bytes: &[u8]) -> Result<Serial> {
|
||||||
if bytes.len() <= 20 {
|
if bytes.len() <= 20 {
|
||||||
Ok(Serial(BigUint::from_bytes_be(&bytes)))
|
Ok(Serial(BigUint::from_bytes_be(bytes)))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ParseError)
|
Err(Error::ParseError)
|
||||||
}
|
}
|
||||||
@@ -192,7 +190,7 @@ impl PublicKeyInfo {
|
|||||||
fn parse(subject_pki: &SubjectPublicKeyInfo<'_>) -> Result<Self> {
|
fn parse(subject_pki: &SubjectPublicKeyInfo<'_>) -> Result<Self> {
|
||||||
match subject_pki.algorithm.algorithm.to_string().as_str() {
|
match subject_pki.algorithm.algorithm.to_string().as_str() {
|
||||||
OID_RSA_ENCRYPTION => {
|
OID_RSA_ENCRYPTION => {
|
||||||
let pubkey = read_pki::rsa_pubkey(subject_pki.subject_public_key.data)?;
|
let pubkey = read_pki::rsa_pubkey(&subject_pki.subject_public_key.data)?;
|
||||||
|
|
||||||
Ok(PublicKeyInfo::Rsa {
|
Ok(PublicKeyInfo::Rsa {
|
||||||
algorithm: match pubkey.n().bits() {
|
algorithm: match pubkey.n().bits() {
|
||||||
@@ -212,10 +210,10 @@ impl PublicKeyInfo {
|
|||||||
.ok_or(Error::InvalidObject)?;
|
.ok_or(Error::InvalidObject)?;
|
||||||
|
|
||||||
match read_pki::ec_parameters(algorithm_parameters)? {
|
match read_pki::ec_parameters(algorithm_parameters)? {
|
||||||
AlgorithmId::EccP256 => EcPublicKey::from_bytes(key_bytes)
|
AlgorithmId::EccP256 => EcPublicKey::<NistP256>::from_bytes(key_bytes)
|
||||||
.map(PublicKeyInfo::EcP256)
|
.map(PublicKeyInfo::EcP256)
|
||||||
.map_err(|_| Error::InvalidObject),
|
.map_err(|_| Error::InvalidObject),
|
||||||
AlgorithmId::EccP384 => EcPublicKey::from_bytes(key_bytes)
|
AlgorithmId::EccP384 => EcPublicKey::<NistP384>::from_bytes(key_bytes)
|
||||||
.map(PublicKeyInfo::EcP384)
|
.map(PublicKeyInfo::EcP384)
|
||||||
.map_err(|_| Error::InvalidObject),
|
.map_err(|_| Error::InvalidObject),
|
||||||
_ => Err(Error::AlgorithmError),
|
_ => Err(Error::AlgorithmError),
|
||||||
@@ -320,6 +318,7 @@ impl x509::AlgorithmIdentifier for SignatureId {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Certificate {
|
pub struct Certificate {
|
||||||
serial: Serial,
|
serial: Serial,
|
||||||
|
#[allow(dead_code)]
|
||||||
issuer: String,
|
issuer: String,
|
||||||
subject: String,
|
subject: String,
|
||||||
subject_pki: PublicKeyInfo,
|
subject_pki: PublicKeyInfo,
|
||||||
@@ -364,12 +363,12 @@ impl Certificate {
|
|||||||
&serial.to_bytes(),
|
&serial.to_bytes(),
|
||||||
&signature_algorithm,
|
&signature_algorithm,
|
||||||
// Issuer and subject are the same in self-signed certificates.
|
// Issuer and subject are the same in self-signed certificates.
|
||||||
&subject,
|
subject,
|
||||||
Utc::now(),
|
Utc::now(),
|
||||||
not_after,
|
not_after,
|
||||||
&subject,
|
subject,
|
||||||
&subject_pki,
|
&subject_pki,
|
||||||
&extensions,
|
extensions,
|
||||||
),
|
),
|
||||||
tbs_cert.deref_mut(),
|
tbs_cert.deref_mut(),
|
||||||
)
|
)
|
||||||
@@ -588,6 +587,7 @@ pub(crate) fn write_certificate(
|
|||||||
|
|
||||||
mod read_pki {
|
mod read_pki {
|
||||||
use der_parser::{
|
use der_parser::{
|
||||||
|
asn1_rs::Any,
|
||||||
ber::BerObjectContent,
|
ber::BerObjectContent,
|
||||||
der::{parse_der_integer, parse_der_sequence_defined_g, DerObject},
|
der::{parse_der_integer, parse_der_sequence_defined_g, DerObject},
|
||||||
error::BerError,
|
error::BerError,
|
||||||
@@ -641,8 +641,8 @@ mod read_pki {
|
|||||||
/// -- specifiedCurve SpecifiedECDomain
|
/// -- specifiedCurve SpecifiedECDomain
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub(super) fn ec_parameters(parameters: &DerObject<'_>) -> Result<AlgorithmId> {
|
pub(super) fn ec_parameters(parameters: &Any<'_>) -> Result<AlgorithmId> {
|
||||||
let curve_oid = parameters.as_oid_val().map_err(|_| Error::InvalidObject)?;
|
let curve_oid = parameters.as_oid().map_err(|_| Error::InvalidObject)?;
|
||||||
|
|
||||||
match curve_oid.to_string().as_str() {
|
match curve_oid.to_string().as_str() {
|
||||||
OID_NIST_P256 => Ok(AlgorithmId::EccP256),
|
OID_NIST_P256 => Ok(AlgorithmId::EccP256),
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
|
|
||||||
use crate::{Error, Result, YubiKey};
|
use crate::{Error, Result, YubiKey};
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryInto,
|
|
||||||
fmt::{self, Debug, Display},
|
fmt::{self, Debug, Display},
|
||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-4
@@ -41,10 +41,7 @@ use crate::{
|
|||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::{
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
convert::TryInto,
|
|
||||||
time::{Duration, SystemTime, UNIX_EPOCH},
|
|
||||||
};
|
|
||||||
|
|
||||||
const CB_ADMIN_TIMESTAMP: usize = 0x04;
|
const CB_ADMIN_TIMESTAMP: usize = 0x04;
|
||||||
const PROTECTED_FLAGS_1_PUK_NOBLOCK: u8 = 0x01;
|
const PROTECTED_FLAGS_1_PUK_NOBLOCK: u8 = 0x01;
|
||||||
|
|||||||
+2
-3
@@ -17,7 +17,7 @@
|
|||||||
//! on which devices support PIV and the available functionality.
|
//! on which devices support PIV and the available functionality.
|
||||||
//!
|
//!
|
||||||
//! # Minimum Supported Rust Version
|
//! # Minimum Supported Rust Version
|
||||||
//! Rust **1.51** or newer.
|
//! Rust **1.57** or newer.
|
||||||
//!
|
//!
|
||||||
//! # Supported YubiKeys
|
//! # Supported YubiKeys
|
||||||
//! - [YubiKey 4] series
|
//! - [YubiKey 4] series
|
||||||
@@ -130,8 +130,7 @@
|
|||||||
|
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iqlusioninc/yubikey.rs/main/img/logo.png",
|
html_logo_url = "https://raw.githubusercontent.com/iqlusioninc/yubikey.rs/main/img/logo.png"
|
||||||
html_root_url = "https://docs.rs/yubikey/0.5.0"
|
|
||||||
)]
|
)]
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
#![warn(missing_docs, rust_2018_idioms, trivial_casts, unused_qualifications)]
|
#![warn(missing_docs, rust_2018_idioms, trivial_casts, unused_qualifications)]
|
||||||
|
|||||||
+3
-4
@@ -33,7 +33,6 @@
|
|||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
use log::error;
|
use log::error;
|
||||||
use rand_core::{OsRng, RngCore};
|
use rand_core::{OsRng, RngCore};
|
||||||
use std::convert::{TryFrom, TryInto};
|
|
||||||
use zeroize::{Zeroize, Zeroizing};
|
use zeroize::{Zeroize, Zeroizing};
|
||||||
|
|
||||||
#[cfg(feature = "untested")]
|
#[cfg(feature = "untested")]
|
||||||
@@ -43,7 +42,7 @@ use crate::{
|
|||||||
yubikey::YubiKey,
|
yubikey::YubiKey,
|
||||||
};
|
};
|
||||||
use des::{
|
use des::{
|
||||||
cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, NewBlockCipher},
|
cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit},
|
||||||
TdesEde3,
|
TdesEde3,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "untested")]
|
#[cfg(feature = "untested")]
|
||||||
@@ -138,7 +137,7 @@ impl MgmKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut mgm = [0u8; DES_LEN_3DES];
|
let mut mgm = [0u8; DES_LEN_3DES];
|
||||||
pbkdf2::<Hmac<Sha1>>(pin, &salt, ITER_MGM_PBKDF2, &mut mgm);
|
pbkdf2::<Hmac<Sha1>>(pin, salt, ITER_MGM_PBKDF2, &mut mgm);
|
||||||
MgmKey::from_bytes(mgm)
|
MgmKey::from_bytes(mgm)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +190,7 @@ impl MgmKey {
|
|||||||
pub fn set_manual(&self, yubikey: &mut YubiKey, require_touch: bool) -> Result<()> {
|
pub fn set_manual(&self, yubikey: &mut YubiKey, require_touch: bool) -> Result<()> {
|
||||||
let txn = yubikey.begin_transaction()?;
|
let txn = yubikey.begin_transaction()?;
|
||||||
|
|
||||||
txn.set_mgm_key(&self, require_touch).map_err(|e| {
|
txn.set_mgm_key(self, require_touch).map_err(|e| {
|
||||||
// Log a warning, since the device mgm key is corrupt or we're in a state
|
// Log a warning, since the device mgm key is corrupt or we're in a state
|
||||||
// where we can't set the mgm key.
|
// where we can't set the mgm key.
|
||||||
error!("could not set new derived mgm key, err = {}", e);
|
error!("could not set new derived mgm key, err = {}", e);
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
|
|
||||||
use crate::{consts::CB_OBJ_MAX, piv::SlotId, serialization::*, Error, Result, YubiKey};
|
use crate::{consts::CB_OBJ_MAX, piv::SlotId, serialization::*, Error, Result, YubiKey};
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::convert::{TryFrom, TryInto};
|
|
||||||
|
|
||||||
const OBJ_MSCMAP: u32 = 0x005f_ff10;
|
const OBJ_MSCMAP: u32 = 0x005f_ff10;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -111,7 +111,7 @@ impl MsRoots {
|
|||||||
let mut data_chunk: usize;
|
let mut data_chunk: usize;
|
||||||
let data = &self.0;
|
let data = &self.0;
|
||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
let n_objs: usize;
|
|
||||||
let txn = yubikey.begin_transaction()?;
|
let txn = yubikey.begin_transaction()?;
|
||||||
|
|
||||||
if data_len == 0 {
|
if data_len == 0 {
|
||||||
@@ -119,7 +119,7 @@ impl MsRoots {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate number of objects required to store blob
|
// Calculate number of objects required to store blob
|
||||||
n_objs = (data_len / (CB_OBJ_MAX - CB_OBJ_TAG_MAX)) + 1;
|
let n_objs: usize = (data_len / (CB_OBJ_MAX - CB_OBJ_TAG_MAX)) + 1;
|
||||||
|
|
||||||
if n_objs > 5 {
|
if n_objs > 5 {
|
||||||
return Err(Error::SizeError);
|
return Err(Error::SizeError);
|
||||||
|
|||||||
+31
-7
@@ -54,8 +54,13 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use elliptic_curve::sec1::EncodedPoint as EcPublicKey;
|
use elliptic_curve::sec1::EncodedPoint as EcPublicKey;
|
||||||
use log::{debug, error, warn};
|
use log::{debug, error, warn};
|
||||||
|
use p256::NistP256;
|
||||||
|
use p384::NistP384;
|
||||||
use rsa::{BigUint, RsaPublicKey};
|
use rsa::{BigUint, RsaPublicKey};
|
||||||
use std::{convert::TryFrom, str::FromStr};
|
use std::{
|
||||||
|
fmt::{Display, Formatter},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "untested")]
|
#[cfg(feature = "untested")]
|
||||||
use {
|
use {
|
||||||
@@ -83,7 +88,7 @@ const KEYDATA_RSA_EXP: u64 = 65537;
|
|||||||
|
|
||||||
/// Slot identifiers.
|
/// Slot identifiers.
|
||||||
/// <https://developers.yubico.com/PIV/Introduction/Certificate_slots.html>
|
/// <https://developers.yubico.com/PIV/Introduction/Certificate_slots.html>
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum SlotId {
|
pub enum SlotId {
|
||||||
/// This certificate and its associated private key is used to authenticate the card
|
/// This certificate and its associated private key is used to authenticate the card
|
||||||
/// and the cardholder. This slot is used for things like system login. The end user
|
/// and the cardholder. This slot is used for things like system login. The end user
|
||||||
@@ -151,6 +156,15 @@ impl From<SlotId> for u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for SlotId {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
SlotId::Retired(r) => write!(f, "{:?}", r),
|
||||||
|
_ => write!(f, "{:?}", self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for SlotId {
|
impl FromStr for SlotId {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
@@ -182,7 +196,7 @@ impl SlotId {
|
|||||||
|
|
||||||
/// Retired slot IDs.
|
/// Retired slot IDs.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
pub enum RetiredSlotId {
|
pub enum RetiredSlotId {
|
||||||
R1,
|
R1,
|
||||||
R2,
|
R2,
|
||||||
@@ -293,6 +307,12 @@ impl From<RetiredSlotId> for u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for RetiredSlotId {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RetiredSlotId {
|
impl RetiredSlotId {
|
||||||
/// Returns the [`ObjectId`] that corresponds to a given [`RetiredSlotId`].
|
/// Returns the [`ObjectId`] that corresponds to a given [`RetiredSlotId`].
|
||||||
pub(crate) fn object_id(self) -> ObjectId {
|
pub(crate) fn object_id(self) -> ObjectId {
|
||||||
@@ -657,10 +677,14 @@ pub fn generate(
|
|||||||
|
|
||||||
let point = tlv.value.to_vec();
|
let point = tlv.value.to_vec();
|
||||||
|
|
||||||
if let AlgorithmId::EccP256 = algorithm {
|
match algorithm {
|
||||||
EcPublicKey::from_bytes(point).map(PublicKeyInfo::EcP256)
|
AlgorithmId::EccP256 => {
|
||||||
} else {
|
EcPublicKey::<NistP256>::from_bytes(point).map(PublicKeyInfo::EcP256)
|
||||||
EcPublicKey::from_bytes(point).map(PublicKeyInfo::EcP384)
|
}
|
||||||
|
AlgorithmId::EccP384 => {
|
||||||
|
EcPublicKey::<NistP384>::from_bytes(point).map(PublicKeyInfo::EcP384)
|
||||||
|
}
|
||||||
|
_ => return Err(Error::AlgorithmError),
|
||||||
}
|
}
|
||||||
.map_err(|_| Error::InvalidObject)
|
.map_err(|_| Error::InvalidObject)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,6 @@
|
|||||||
use crate::{Result, YubiKey};
|
use crate::{Result, YubiKey};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
convert::TryInto,
|
|
||||||
ffi::CStr,
|
ffi::CStr,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
@@ -45,6 +44,7 @@ impl Context {
|
|||||||
c.list_readers(reader_names)?.collect()
|
c.list_readers(reader_names)?.collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[allow(clippy::needless_collect)]
|
||||||
let readers: Vec<_> = reader_cstrs
|
let readers: Vec<_> = reader_cstrs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name| Reader::new(name, Arc::clone(ctx)))
|
.map(|name| Reader::new(name, Arc::clone(ctx)))
|
||||||
|
|||||||
+2
-11
@@ -65,7 +65,7 @@ impl Default for SettingSource {
|
|||||||
/// These can be configured globally in `/etc/yubico/yubikeypiv.conf` by a
|
/// These can be configured globally in `/etc/yubico/yubikeypiv.conf` by a
|
||||||
/// system administrator, or by the local user via `YUBIKEY_PIV_*` environment
|
/// system administrator, or by the local user via `YUBIKEY_PIV_*` environment
|
||||||
/// variables.
|
/// variables.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
pub struct Setting {
|
pub struct Setting {
|
||||||
/// Boolean value
|
/// Boolean value
|
||||||
pub value: bool,
|
pub value: bool,
|
||||||
@@ -99,7 +99,7 @@ impl Setting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (name, value) = {
|
let (name, value) = {
|
||||||
let mut parts = line.splitn(1, '=');
|
let mut parts = line.splitn(2, '=');
|
||||||
let name = parts.next();
|
let name = parts.next();
|
||||||
let value = parts.next();
|
let value = parts.next();
|
||||||
match (name, value, parts.next()) {
|
match (name, value, parts.next()) {
|
||||||
@@ -130,12 +130,3 @@ impl Setting {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Setting {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
value: false,
|
|
||||||
source: SettingSource::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ use crate::{
|
|||||||
Buffer, ObjectId,
|
Buffer, ObjectId,
|
||||||
};
|
};
|
||||||
use log::{error, trace};
|
use log::{error, trace};
|
||||||
use std::convert::TryInto;
|
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
#[cfg(feature = "untested")]
|
#[cfg(feature = "untested")]
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ use log::{error, info};
|
|||||||
use pcsc::Card;
|
use pcsc::Card;
|
||||||
use rand_core::{OsRng, RngCore};
|
use rand_core::{OsRng, RngCore};
|
||||||
use std::{
|
use std::{
|
||||||
convert::{TryFrom, TryInto},
|
|
||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|||||||
+34
-1
@@ -8,7 +8,7 @@ use log::trace;
|
|||||||
use rand_core::{OsRng, RngCore};
|
use rand_core::{OsRng, RngCore};
|
||||||
use rsa::{hash::Hash::SHA2_256, PaddingScheme, PublicKey};
|
use rsa::{hash::Hash::SHA2_256, PaddingScheme, PublicKey};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::{convert::TryInto, env, sync::Mutex};
|
use std::{env, sync::Mutex};
|
||||||
use x509::RelativeDistinguishedName;
|
use x509::RelativeDistinguishedName;
|
||||||
use yubikey::{
|
use yubikey::{
|
||||||
certificate::{Certificate, PublicKeyInfo},
|
certificate::{Certificate, PublicKeyInfo},
|
||||||
@@ -241,3 +241,36 @@ fn generate_self_signed_ec_cert() {
|
|||||||
use p256::ecdsa::signature::Verifier;
|
use p256::ecdsa::signature::Verifier;
|
||||||
assert!(vk.verify(msg, &sig).is_ok());
|
assert!(vk.verify(msg, &sig).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_slot_id_display() {
|
||||||
|
assert_eq!(format!("{}", SlotId::Authentication), "Authentication");
|
||||||
|
assert_eq!(format!("{}", SlotId::Signature), "Signature");
|
||||||
|
assert_eq!(format!("{}", SlotId::KeyManagement), "KeyManagement");
|
||||||
|
assert_eq!(
|
||||||
|
format!("{}", SlotId::CardAuthentication),
|
||||||
|
"CardAuthentication"
|
||||||
|
);
|
||||||
|
assert_eq!(format!("{}", SlotId::Attestation), "Attestation");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R1)), "R1");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R2)), "R2");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R3)), "R3");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R4)), "R4");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R5)), "R5");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R6)), "R6");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R7)), "R7");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R8)), "R8");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R9)), "R9");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R10)), "R10");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R11)), "R11");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R12)), "R12");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R13)), "R13");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R14)), "R14");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R15)), "R15");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R16)), "R16");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R17)), "R17");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R18)), "R18");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R19)), "R19");
|
||||||
|
assert_eq!(format!("{}", SlotId::Retired(RetiredSlotId::R20)), "R20");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user