Compare commits

...

28 Commits

Author SHA1 Message Date
Tony Arcieri (iqlusion) b571f81007 yubikey-cli v0.6.0 (#404) 2022-08-10 17:23:41 -07:00
Tony Arcieri (iqlusion) 0a36a37ae3 yubikey v0.6.0 (#403) 2022-08-10 16:41:26 -07:00
Tony Arcieri (iqlusion) 3463d109b2 Bump der-parser to v8; x509-parser to v0.14 (#402) 2022-08-10 15:19:21 -07:00
dependabot[bot] 014b7ee6fd Bump p384 from 0.10.0 to 0.11.2 (#401)
Bumps [p384](https://github.com/RustCrypto/elliptic-curves) from 0.10.0 to 0.11.2.
- [Release notes](https://github.com/RustCrypto/elliptic-curves/releases)
- [Commits](https://github.com/RustCrypto/elliptic-curves/compare/p384/v0.10.0...p384/v0.11.2)

---
updated-dependencies:
- dependency-name: p384
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-10 14:57:39 -07:00
vdods 498de4c10d Adding some common traits for certain enum types to support maps. (#372) 2022-08-10 14:34:58 -07:00
Tony Arcieri (iqlusion) 98b038c873 Cargo.lock: bump dependencies (#400) 2022-08-10 14:26:33 -07:00
Tony Arcieri (iqlusion) fab9d25b0a cli: migrate from gumdrop to clap v3 (#379)
`gumdrop` was originally chosen for its minimalist set of dependencies,
but `clap` v3 has a slimmed down set of dependencies and better UX.
2022-05-24 21:45:26 -06:00
dependabot[bot] bb80551324 Bump uuid from 0.8.2 to 1.0.0 (#376)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 0.8.2 to 1.0.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/0.8.2...1.0.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-23 20:18:58 -07:00
Tony Arcieri (iqlusion) 9e20ecfe55 RustCrypto crate upgrades; MSRV 1.57 (#378)
Updates all of the RustCrypto dependencies to the latest versions:

- `des` v0.8
- `elliptic-curve` v0.12
- `hmac` v0.12
- `num-bigint-dig` v0.8
- `pbkdf2` v0.11
- `p256` v0.11
- `p384` v0.10
- `rsa` v0.6
- `sha1` v0.10 (replacing `sha-1`)
- `sha2` v0.10
2022-05-23 20:04:12 -07:00
Tony Arcieri (iqlusion) fac83c60fb Cargo.lock: bump dependencies (#375) 2022-05-23 17:52:53 -07:00
Shella Stephens 914f9bee0d Cargo.lock: update dependencies & fix cargo audit (#365) 2022-03-07 16:29:35 -07:00
Ferdinand Linnenberg 83de59983f Add Display formatter to SlotId (#353) 2022-02-11 13:10:53 -08:00
Shella Stephens e21395c934 Cargo.lock: update dependencies (#347) 2022-01-31 08:00:16 -07:00
Tony Arcieri (iqlusion) 935fea0868 Bump p256 => v0.10; p384 => v0.9 (#344) 2022-01-17 15:08:48 -08:00
Tony Arcieri (iqlusion) dd4b1c60a4 2021 edition upgrade; MSRV 1.56 (#343)
Changes the `edition` to 2021 in both the `yubikey` and `yubikey-cli`
crates.

Removes `TryFrom`/`TryInto` imports, now that they're in the prelude.
2022-01-17 14:54:01 -08:00
Shella Stephens 74a50f0f0c Bump dependencies & fix security audit (#340)
* Bump dependencies & fix security audit

* allow dead code for issuer field #[allow(dead_code)] in Certificates struct
2022-01-10 08:40:58 -07:00
Tony Arcieri (iqlusion) 86d482b38d yubikey-cli v0.5.0 (#328) 2021-11-21 08:10:17 -08:00
Tony Arcieri (iqlusion) edf74871ba yubikey v0.5.0 (#327) 2021-11-21 07:42:39 -08:00
Tony Arcieri (iqlusion) b11d5c409b Cargo.lock: bump dependencies (#326) 2021-11-21 07:06:17 -08:00
str4d 52107281df nom 7 (#322) 2021-10-19 06:38:38 -07:00
Shella Stephens bcef792f69 Update dependencies & add RUSTSEC-2020-0071 to audit.toml (#323) 2021-10-18 17:07:32 -06:00
Tony Arcieri (iqlusion) 10a7ead932 Cargo.lock: bump dependencies (#317) 2021-09-11 13:55:34 -07:00
Benno Rice 54ce90d51d Update dependencies (#315)
* Update rsa dependency to 0.5

* Update pbkdf dependency to 0.9

* Update x509-parser dependency to 0.11

* Update crypto-bigint subdepdendency to 0.2.6
2021-09-10 10:44:59 -07:00
Tony Arcieri (iqlusion) 3905104b52 Cargo.lock: bump dependencies (#308) 2021-08-20 18:09:51 -07:00
Tony Arcieri (iqlusion) 97e15abcee Cargo.lock: bump dependencies (#304) 2021-07-26 14:52:06 -07:00
Shella Stephens da7e7af109 Add deps.rs badge (#299) 2021-07-19 15:07:41 -07:00
Shella Stephens 6e96087b93 Cargo.lock: update deps (#300) 2021-07-19 15:00:16 -07:00
Tony Arcieri (iqlusion) f3bb858a2f Cargo.lock: bump dependencies (#298) 2021-07-19 09:05:32 -07:00
27 changed files with 926 additions and 530 deletions
+5
View File
@@ -0,0 +1,5 @@
[advisories]
ignore = [
"RUSTSEC-2020-0071", # time
"RUSTSEC-2020-0159", # chrono
]
+4 -4
View File
@@ -36,13 +36,13 @@ jobs:
toolchain: stable
deps: true
- platform: ubuntu-latest
toolchain: 1.51.0 # MSRV
toolchain: 1.57.0 # MSRV
deps: sudo apt-get install libpcsclite-dev
- platform: windows-latest
toolchain: 1.51.0 # MSRV
toolchain: 1.57.0 # MSRV
deps: true
- platform: macos-latest
toolchain: 1.51.0 # MSRV
toolchain: 1.57.0 # MSRV
deps: true
runs-on: ${{ matrix.platform }}
steps:
@@ -82,7 +82,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: 1.51.0 # MSRV
toolchain: 1.57.0 # MSRV
components: clippy
override: true
- run: sudo apt-get install libpcsclite-dev
+33
View File
@@ -4,6 +4,39 @@ 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/),
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)
### Changed
- Update `rsa` dependency to 0.5 ([#315])
- Update `pbkdf2` dependency to 0.9 ([#315])
- Update `x509-parser` dependency to 0.12 ([#315], [#322])
- Update `nom` to v7.0 ([#322])
[#315]: https://github.com/iqlusioninc/yubikey.rs/pull/315
[#322]: https://github.com/iqlusioninc/yubikey.rs/pull/322
## 0.4.2 (2021-07-13)
### Added
- Make `yubikey::Buffer` a pub type ([#290])
Generated
+695 -323
View File
File diff suppressed because it is too large Load Diff
+19 -18
View File
@@ -1,6 +1,6 @@
[package]
name = "yubikey"
version = "0.4.2" # Also update html_root_url in lib.rs when bumping this
version = "0.6.0"
description = """
Pure Rust cross-platform host-side driver for YubiKey devices from Yubico with
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
"""
authors = ["Tony Arcieri <tony@iqlusion.io>", "Yubico AB"]
edition = "2018"
license = "BSD-2-Clause"
repository = "https://github.com/iqlusioninc/yubikey.rs"
readme = "README.md"
categories = ["api-bindings", "cryptography", "hardware-support"]
keywords = ["ecdsa", "encryption", "rsa", "piv", "signature"]
edition = "2021"
rust-version = "1.57"
[workspace]
members = [".", "cli"]
@@ -21,33 +22,33 @@ members = [".", "cli"]
[dependencies]
chrono = "0.4"
cookie-factory = "0.3"
der-parser = "5"
des = "0.7"
elliptic-curve = "0.10"
hmac = "0.11"
der-parser = "8"
des = "0.8"
elliptic-curve = "0.12"
hmac = "0.12"
log = "0.4"
nom = "6"
num-bigint-dig = { version = "0.7", features = ["rand"] }
nom = "7"
num-bigint-dig = { version = "0.8", features = ["rand"] }
num-traits = "0.2"
num-integer = "0.1"
pbkdf2 = { version = "0.8", default-features = false }
p256 = "0.9"
p384 = "0.8"
pbkdf2 = { version = "0.11", default-features = false }
p256 = "0.11"
p384 = "0.11"
pcsc = "2"
rand_core = { version = "0.6", features = ["std"] }
rsa = "0.4"
secrecy = "0.7"
sha-1 = "0.9"
sha2 = "0.9"
rsa = "0.6"
secrecy = "0.8"
sha1 = "0.10"
sha2 = "0.10"
subtle = "2"
subtle-encoding = "0.5"
uuid = { version = "0.8", features = ["v4"] }
uuid = { version = "1.0", features = ["v4"] }
x509 = "0.2"
x509-parser = "0.9"
x509-parser = "0.14"
zeroize = "1"
[dev-dependencies]
env_logger = "0.8"
env_logger = "0.9"
lazy_static = "1"
[features]
+9 -6
View File
@@ -5,9 +5,10 @@
[![crate][crate-image]][crate-link]
[![Docs][docs-image]][docs-link]
[![2-Clause BSD Licensed][license-image]][license-link]
![Rust Version][rustc-image]
![MSRV][msrv-image]
[![Safety Dance][safety-image]][safety-link]
[![Build Status][build-image]][build-link]
[![dependency status][deps-image]][deps-link]
Pure Rust cross-platform host-side driver for [YubiKey] devices from [Yubico]
with support for public-key encryption and digital signatures using the
@@ -25,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
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
private key generated and stored on a Yubikey (with option PIN-based access),
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),
this is the crate you've been after!
Note that while this project started as a fork of a [Yubico] project,
@@ -35,7 +36,7 @@ endorsed by Yubico.
## Minimum Supported Rust Version
Rust **1.51** or newer.
Rust **1.57** or newer.
## Supported YubiKeys
@@ -122,7 +123,7 @@ Yubico's [yubico-piv-tool], a C library/CLI program. The original library
was licensed under a [2-Clause BSD License][BSDL], which this library inherits
as a derived work.
Copyright (c) 2014-2021 Yubico AB, Tony Arcieri
Copyright (c) 2014-2022 Yubico AB, Tony Arcieri
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -164,11 +165,13 @@ or conditions.
[docs-link]: https://docs.rs/yubikey/
[license-image]: https://img.shields.io/badge/license-BSD-blue.svg
[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-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-link]: https://github.com/iqlusioninc/yubikey.rs/actions
[deps-image]: https://deps.rs/repo/github/iqlusioninc/yubikey.rs/status.svg
[deps-link]: https://deps.rs/repo/github/iqlusioninc/yubikey.rs
[//]: # (general links)
+17 -1
View File
@@ -4,6 +4,22 @@ 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/),
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; MSRV 1.57 ([#343])
- Migrate from `gumdrop` to `clap` v3 ([#379])
- Bump `yubikey` dependency to v0.6 ([#403])
[#343]: https://github.com/iqlusioninc/yubikey.rs/pull/343
[#379]: https://github.com/iqlusioninc/yubikey.rs/pull/379
[#403]: https://github.com/iqlusioninc/yubikey.rs/pull/403
## 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)
### Changed
- Switch to renamed `yubikey` crate ([#283])
@@ -30,7 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `status` command ([#72], [#74])
### Changed
- Bump `yubikey-piv` to v0.1.0 ([#180])
- Bump `yubikey-piv` to v0.1 ([#180])
- Bump `x509-parser` to v0.8 ([#181])
- Bump `sha2` to v0.9 ([#182])
- Rename `list` command to `readers`; improve usage ([#71])
+7 -6
View File
@@ -1,25 +1,26 @@
[package]
name = "yubikey-cli"
version = "0.4.0"
version = "0.6.0"
description = """
Command-line interface for performing encryption and signing using RSA/ECC keys
stored on YubiKey devices.
"""
authors = ["Tony Arcieri <tony@iqlusion.io>"]
edition = "2018"
license = "BSD-2-Clause"
repository = "https://github.com/iqlusioninc/yubikey.rs"
readme = "README.md"
categories = ["command-line-utilities", "cryptography", "hardware-support"]
keywords = ["ecdsa", "rsa", "piv", "pcsc", "yubikey"]
edition = "2021"
rust-version = "1.56"
[dependencies]
gumdrop = "0.8"
env_logger = "0.8"
clap = { version = "3", features = ["derive"] }
env_logger = "0.9"
lazy_static = "1"
log = "0.4"
sha2 = "0.9"
subtle-encoding = "0.5"
termcolor = "1"
x509-parser = "0.9"
yubikey = { version = "0.4", path = ".." }
x509-parser = "0.12"
yubikey = { version = "0.6", path = ".." }
+3 -7
View File
@@ -18,7 +18,7 @@ utility with general-purpose public-key encryption and signing support.
## Minimum Supported Rust Version
Rust **1.51** or newer.
Rust **1.57** or newer.
## Supported YubiKeys
@@ -35,10 +35,6 @@ an experimental stage and may still contain high-severity issues.
USE AT YOUR OWN RISK!
## Status
WIP. Check back later.
## Code of Conduct
We abide by the [Contributor Covenant][cc-md] and ask that you do as well.
@@ -47,7 +43,7 @@ For more information, please see [CODE_OF_CONDUCT.md][cc-md].
## License
Copyright (c) 2014-2021 Yubico AB, Tony Arcieri
Copyright (c) 2014-2022 Yubico AB, Tony Arcieri
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -88,7 +84,7 @@ or conditions.
[docs-image]: https://docs.rs/yubikey-cli/badge.svg
[docs-link]: https://docs.rs/yubikey-cli/
[license-image]: https://img.shields.io/badge/license-BSD-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.39+-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.57+-blue.svg
[maintenance-image]: https://img.shields.io/badge/maintenance-experimental-blue.svg
[safety-image]: https://img.shields.io/badge/unsafe-forbidden-success.svg
[safety-link]: https://github.com/rust-secure-code/safety-dance/
+2 -2
View File
@@ -8,9 +8,9 @@
unused_qualifications
)]
use gumdrop::Options;
use clap::Parser;
use yubikey_cli::commands::YubiKeyCli;
fn main() {
YubiKeyCli::parse_args_default_or_exit().run();
YubiKeyCli::parse().run()
}
+15 -80
View File
@@ -4,62 +4,25 @@ pub mod readers;
pub mod status;
use self::{readers::ReadersCmd, status::StatusCmd};
use crate::terminal::{self, STDOUT};
use gumdrop::Options;
use std::{
env,
io::{self, Write},
process::exit,
};
use termcolor::{ColorChoice, ColorSpec, WriteColor};
use crate::terminal;
use clap::Parser;
use std::{env, process::exit};
use termcolor::ColorChoice;
use yubikey::{Serial, YubiKey};
/// The `yubikey` CLI utility
#[derive(Debug, Options)]
#[derive(Debug, Parser)]
pub struct YubiKeyCli {
/// Obtain help about the current command
#[options(short = "h", help = "print help message")]
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"
)]
/// Serial number of the YubiKey to connect to
#[clap(short = 's', long = "serial")]
pub serial: Option<Serial>,
/// Subcommand to execute.
#[options(command)]
pub command: Option<Commands>,
#[clap(subcommand)]
pub command: Commands,
}
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
pub fn run(&self) {
// TODO(tarcieri): make this more configurable
@@ -70,10 +33,7 @@ impl YubiKeyCli {
env_logger::builder().format_timestamp(None).init();
}
match &self.command {
Some(cmd) => cmd.run(self.yubikey_init()),
None => Self::print_usage().unwrap(),
}
self.command.run(self.yubikey_init())
}
/// Initialize the YubiKey client driver
@@ -92,22 +52,18 @@ impl YubiKeyCli {
}
/// Subcommands of this application
#[derive(Debug, Options)]
#[derive(Debug, Parser)]
pub enum Commands {
/// `help` subcommand
#[options(help = "show help for a command")]
Help(HelpOpts),
/// `version` subcommand
#[options(help = "display version information")]
#[clap(about = "display version information")]
Version(VersionOpts),
/// `readers` subcommand
#[options(help = "list detected readers")]
#[clap(about = "list detected readers")]
Readers(ReadersCmd),
/// `status` subcommand
#[options(help = "show yubikey status")]
#[clap(about = "show yubikey status")]
Status(StatusCmd),
}
@@ -115,7 +71,6 @@ impl Commands {
/// Run the given command
pub fn run(&self, yubikey: YubiKey) {
match self {
Commands::Help(help) => help.run(),
Commands::Version(version) => version.run(),
Commands::Readers(list) => list.run(),
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
#[derive(Debug, Options)]
#[derive(Debug, Parser)]
pub struct VersionOpts {}
impl VersionOpts {
+2 -2
View File
@@ -1,7 +1,7 @@
//! List detected readers
use crate::terminal::STDOUT;
use gumdrop::Options;
use clap::Parser;
use std::{
io::{self, Write},
process::exit,
@@ -10,7 +10,7 @@ use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
use yubikey::{Context, Serial};
/// The `readers` subcommand
#[derive(Debug, Options)]
#[derive(Debug, Parser)]
pub struct ReadersCmd {}
impl ReadersCmd {
+2 -2
View File
@@ -1,7 +1,7 @@
//! Print device status
use crate::terminal::{print_cert_info, STDOUT};
use gumdrop::Options;
use clap::Parser;
use std::io::{self, Write};
use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
use yubikey::{piv::*, YubiKey};
@@ -10,7 +10,7 @@ use yubikey::{piv::*, YubiKey};
const NONE_STR: &str = "<none>";
/// The `status` subcommand
#[derive(Debug, Options)]
#[derive(Debug, Parser)]
pub struct StatusCmd {}
impl StatusCmd {
-1
View File
@@ -33,7 +33,6 @@
use crate::{Error, Result, YubiKey};
use rand_core::{OsRng, RngCore};
use std::{
convert::TryInto,
fmt::{self, Debug, Display},
str,
};
+26 -30
View File
@@ -45,11 +45,9 @@ use log::error;
use num_bigint_dig::BigUint;
use p256::NistP256;
use p384::NistP384;
use rsa::{PublicKeyParts, RSAPublicKey};
use rsa::{PublicKeyParts, RsaPublicKey};
use sha2::{Digest, Sha256};
use std::convert::TryFrom;
use std::fmt;
use std::ops::DerefMut;
use std::{fmt, ops::DerefMut};
use x509::{der::Oid, RelativeDistinguishedName};
use x509_parser::{parse_x509_certificate, x509::SubjectPublicKeyInfo};
use zeroize::Zeroizing;
@@ -85,7 +83,7 @@ impl TryFrom<&[u8]> for Serial {
fn try_from(bytes: &[u8]) -> Result<Serial> {
if bytes.len() <= 20 {
Ok(Serial(BigUint::from_bytes_be(&bytes)))
Ok(Serial(BigUint::from_bytes_be(bytes)))
} else {
Err(Error::ParseError)
}
@@ -172,7 +170,7 @@ pub enum PublicKeyInfo {
algorithm: AlgorithmId,
/// Public key
pubkey: RSAPublicKey,
pubkey: RsaPublicKey,
},
/// EC P-256 keys
@@ -192,7 +190,7 @@ impl PublicKeyInfo {
fn parse(subject_pki: &SubjectPublicKeyInfo<'_>) -> Result<Self> {
match subject_pki.algorithm.algorithm.to_string().as_str() {
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 {
algorithm: match pubkey.n().bits() {
@@ -212,10 +210,10 @@ impl PublicKeyInfo {
.ok_or(Error::InvalidObject)?;
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_err(|_| Error::InvalidObject),
AlgorithmId::EccP384 => EcPublicKey::from_bytes(key_bytes)
AlgorithmId::EccP384 => EcPublicKey::<NistP384>::from_bytes(key_bytes)
.map(PublicKeyInfo::EcP384)
.map_err(|_| Error::InvalidObject),
_ => Err(Error::AlgorithmError),
@@ -320,6 +318,7 @@ impl x509::AlgorithmIdentifier for SignatureId {
#[derive(Clone, Debug)]
pub struct Certificate {
serial: Serial,
#[allow(dead_code)]
issuer: String,
subject: String,
subject_pki: PublicKeyInfo,
@@ -364,12 +363,12 @@ impl Certificate {
&serial.to_bytes(),
&signature_algorithm,
// Issuer and subject are the same in self-signed certificates.
&subject,
subject,
Utc::now(),
not_after,
&subject,
subject,
&subject_pki,
&extensions,
extensions,
),
tbs_cert.deref_mut(),
)
@@ -588,13 +587,13 @@ pub(crate) fn write_certificate(
mod read_pki {
use der_parser::{
asn1_rs::Any,
ber::BerObjectContent,
der::{parse_der_integer, DerObject},
der::{parse_der_integer, parse_der_sequence_defined_g, DerObject},
error::BerError,
*,
};
use nom::{combinator, IResult};
use rsa::{BigUint, RSAPublicKey};
use nom::{combinator, sequence::pair, IResult};
use rsa::{BigUint, RsaPublicKey};
use super::{OID_NIST_P256, OID_NIST_P384};
use crate::{piv::AlgorithmId, Error, Result};
@@ -606,21 +605,18 @@ mod read_pki {
/// publicExponent INTEGER -- e
/// }
/// ```
pub(super) fn rsa_pubkey(encoded: &[u8]) -> Result<RSAPublicKey> {
fn parse_rsa_pubkey(i: &[u8]) -> IResult<&[u8], DerObject<'_>, BerError> {
parse_der_sequence_defined!(i, parse_der_integer >> parse_der_integer)
pub(super) fn rsa_pubkey(encoded: &[u8]) -> Result<RsaPublicKey> {
fn parse_rsa_pubkey(i: &[u8]) -> IResult<&[u8], (DerObject<'_>, DerObject<'_>), BerError> {
parse_der_sequence_defined_g(|i, _| pair(parse_der_integer, parse_der_integer)(i))(i)
}
fn rsa_pubkey_parts(i: &[u8]) -> IResult<&[u8], (BigUint, BigUint), BerError> {
combinator::map(parse_rsa_pubkey, |object| {
let seq = object.as_sequence().expect("is DER sequence");
assert_eq!(seq.len(), 2);
let n = match seq[0].content {
combinator::map(parse_rsa_pubkey, |(modulus, public_exponent)| {
let n = match modulus.content {
BerObjectContent::Integer(s) => BigUint::from_bytes_be(s),
_ => panic!("expected DER integer"),
};
let e = match seq[1].content {
let e = match public_exponent.content {
BerObjectContent::Integer(s) => BigUint::from_bytes_be(s),
_ => panic!("expected DER integer"),
};
@@ -634,7 +630,7 @@ mod read_pki {
_ => return Err(Error::InvalidObject),
};
RSAPublicKey::new(n, e).map_err(|_| Error::InvalidObject)
RsaPublicKey::new(n, e).map_err(|_| Error::InvalidObject)
}
/// From [RFC 5480](https://tools.ietf.org/html/rfc5480#section-2.1.1):
@@ -645,8 +641,8 @@ mod read_pki {
/// -- specifiedCurve SpecifiedECDomain
/// }
/// ```
pub(super) fn ec_parameters(parameters: &DerObject<'_>) -> Result<AlgorithmId> {
let curve_oid = parameters.as_oid_val().map_err(|_| Error::InvalidObject)?;
pub(super) fn ec_parameters(parameters: &Any<'_>) -> Result<AlgorithmId> {
let curve_oid = parameters.as_oid().map_err(|_| Error::InvalidObject)?;
match curve_oid.to_string().as_str() {
OID_NIST_P256 => Ok(AlgorithmId::EccP256),
@@ -658,7 +654,7 @@ mod read_pki {
mod write_pki {
use cookie_factory::{SerializeFn, WriteContext};
use rsa::{BigUint, PublicKeyParts, RSAPublicKey};
use rsa::{BigUint, PublicKeyParts, RsaPublicKey};
use std::io::Write;
use x509::der::write::{der_integer, der_sequence};
@@ -675,7 +671,7 @@ mod write_pki {
/// }
/// ```
pub(super) fn rsa_pubkey<'a, W: Write + 'a>(
pubkey: &'a RSAPublicKey,
pubkey: &'a RsaPublicKey,
) -> impl SerializeFn<W> + 'a {
der_sequence((
der_integer_biguint(pubkey.n()),
-1
View File
@@ -32,7 +32,6 @@
use crate::{Error, Result, YubiKey};
use std::{
convert::TryInto,
fmt::{self, Debug, Display},
str,
};
+1 -4
View File
@@ -41,10 +41,7 @@ use crate::{
Result,
};
use log::error;
use std::{
convert::TryInto,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
const CB_ADMIN_TIMESTAMP: usize = 0x04;
const PROTECTED_FLAGS_1_PUK_NOBLOCK: u8 = 0x01;
+2 -3
View File
@@ -17,7 +17,7 @@
//! on which devices support PIV and the available functionality.
//!
//! # Minimum Supported Rust Version
//! Rust **1.51** or newer.
//! Rust **1.57** or newer.
//!
//! # Supported YubiKeys
//! - [YubiKey 4] series
@@ -130,8 +130,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iqlusioninc/yubikey.rs/main/img/logo.png",
html_root_url = "https://docs.rs/yubikey/0.4.2"
html_logo_url = "https://raw.githubusercontent.com/iqlusioninc/yubikey.rs/main/img/logo.png"
)]
#![forbid(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms, trivial_casts, unused_qualifications)]
+3 -4
View File
@@ -33,7 +33,6 @@
use crate::{Error, Result};
use log::error;
use rand_core::{OsRng, RngCore};
use std::convert::{TryFrom, TryInto};
use zeroize::{Zeroize, Zeroizing};
#[cfg(feature = "untested")]
@@ -43,7 +42,7 @@ use crate::{
yubikey::YubiKey,
};
use des::{
cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, NewBlockCipher},
cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit},
TdesEde3,
};
#[cfg(feature = "untested")]
@@ -138,7 +137,7 @@ impl MgmKey {
}
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)
}
@@ -191,7 +190,7 @@ impl MgmKey {
pub fn set_manual(&self, yubikey: &mut YubiKey, require_touch: bool) -> Result<()> {
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
// where we can't set the mgm key.
error!("could not set new derived mgm key, err = {}", e);
-1
View File
@@ -32,7 +32,6 @@
use crate::{consts::CB_OBJ_MAX, piv::SlotId, serialization::*, Error, Result, YubiKey};
use log::error;
use std::convert::{TryFrom, TryInto};
const OBJ_MSCMAP: u32 = 0x005f_ff10;
+2 -2
View File
@@ -111,7 +111,7 @@ impl MsRoots {
let mut data_chunk: usize;
let data = &self.0;
let data_len = data.len();
let n_objs: usize;
let txn = yubikey.begin_transaction()?;
if data_len == 0 {
@@ -119,7 +119,7 @@ impl MsRoots {
}
// 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 {
return Err(Error::SizeError);
+33 -9
View File
@@ -54,8 +54,13 @@ use crate::{
};
use elliptic_curve::sec1::EncodedPoint as EcPublicKey;
use log::{debug, error, warn};
use rsa::{BigUint, RSAPublicKey};
use std::{convert::TryFrom, str::FromStr};
use p256::NistP256;
use p384::NistP384;
use rsa::{BigUint, RsaPublicKey};
use std::{
fmt::{Display, Formatter},
str::FromStr,
};
#[cfg(feature = "untested")]
use {
@@ -83,7 +88,7 @@ const KEYDATA_RSA_EXP: u64 = 65537;
/// Slot identifiers.
/// <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 {
/// 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
@@ -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 {
type Err = Error;
@@ -182,7 +196,7 @@ impl SlotId {
/// Retired slot IDs.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum RetiredSlotId {
R1,
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 {
/// Returns the [`ObjectId`] that corresponds to a given [`RetiredSlotId`].
pub(crate) fn object_id(self) -> ObjectId {
@@ -624,7 +644,7 @@ pub fn generate(
Ok(PublicKeyInfo::Rsa {
algorithm,
pubkey: RSAPublicKey::new(
pubkey: RsaPublicKey::new(
BigUint::from_bytes_be(&modulus),
BigUint::from_bytes_be(&exp),
)
@@ -657,10 +677,14 @@ pub fn generate(
let point = tlv.value.to_vec();
if let AlgorithmId::EccP256 = algorithm {
EcPublicKey::from_bytes(point).map(PublicKeyInfo::EcP256)
} else {
EcPublicKey::from_bytes(point).map(PublicKeyInfo::EcP384)
match algorithm {
AlgorithmId::EccP256 => {
EcPublicKey::<NistP256>::from_bytes(point).map(PublicKeyInfo::EcP256)
}
AlgorithmId::EccP384 => {
EcPublicKey::<NistP384>::from_bytes(point).map(PublicKeyInfo::EcP384)
}
_ => return Err(Error::AlgorithmError),
}
.map_err(|_| Error::InvalidObject)
}
+1 -1
View File
@@ -3,7 +3,6 @@
use crate::{Result, YubiKey};
use std::{
borrow::Cow,
convert::TryInto,
ffi::CStr,
sync::{Arc, Mutex},
};
@@ -45,6 +44,7 @@ impl Context {
c.list_readers(reader_names)?.collect()
};
#[allow(clippy::needless_collect)]
let readers: Vec<_> = reader_cstrs
.iter()
.map(|name| Reader::new(name, Arc::clone(ctx)))
+2 -11
View File
@@ -65,7 +65,7 @@ impl Default for SettingSource {
/// These can be configured globally in `/etc/yubico/yubikeypiv.conf` by a
/// system administrator, or by the local user via `YUBIKEY_PIV_*` environment
/// variables.
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, Default)]
pub struct Setting {
/// Boolean value
pub value: bool,
@@ -99,7 +99,7 @@ impl Setting {
}
let (name, value) = {
let mut parts = line.splitn(1, '=');
let mut parts = line.splitn(2, '=');
let name = parts.next();
let 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(),
}
}
}
-1
View File
@@ -11,7 +11,6 @@ use crate::{
Buffer, ObjectId,
};
use log::{error, trace};
use std::convert::TryInto;
use zeroize::Zeroizing;
#[cfg(feature = "untested")]
-1
View File
@@ -45,7 +45,6 @@ use log::{error, info};
use pcsc::Card;
use rand_core::{OsRng, RngCore};
use std::{
convert::{TryFrom, TryInto},
fmt::{self, Display},
str::FromStr,
};
+34 -1
View File
@@ -8,7 +8,7 @@ use log::trace;
use rand_core::{OsRng, RngCore};
use rsa::{hash::Hash::SHA2_256, PaddingScheme, PublicKey};
use sha2::{Digest, Sha256};
use std::{convert::TryInto, env, sync::Mutex};
use std::{env, sync::Mutex};
use x509::RelativeDistinguishedName;
use yubikey::{
certificate::{Certificate, PublicKeyInfo},
@@ -241,3 +241,36 @@ fn generate_self_signed_ec_cert() {
use p256::ecdsa::signature::Verifier;
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");
}