Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3580c45f71 | |||
| 79c289ac00 | |||
| cbca858488 | |||
| 8b896ab4de | |||
| 24b035008c | |||
| 90bc878b21 | |||
| 08185c5ec9 | |||
| 7da2c7ba6a | |||
| fecd786262 | |||
| 1a6d1d0a71 | |||
| f43539088b | |||
| 72f63131ac | |||
| b59856d09e | |||
| 7628ebf605 | |||
| 0688dbf30d | |||
| 7e3d0bc838 |
@@ -3,7 +3,7 @@ name: CI
|
||||
on:
|
||||
pull_request: {}
|
||||
push:
|
||||
branches: develop
|
||||
branches: main
|
||||
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
@@ -36,13 +36,13 @@ jobs:
|
||||
toolchain: stable
|
||||
deps: true
|
||||
- platform: ubuntu-latest
|
||||
toolchain: 1.44.0 # MSRV
|
||||
toolchain: 1.46.0 # MSRV
|
||||
deps: sudo apt-get install libpcsclite-dev
|
||||
- platform: windows-latest
|
||||
toolchain: 1.44.0 # MSRV
|
||||
toolchain: 1.46.0 # MSRV
|
||||
deps: true
|
||||
- platform: macos-latest
|
||||
toolchain: 1.44.0 # MSRV
|
||||
toolchain: 1.46.0 # MSRV
|
||||
deps: true
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: 1.44.0 # MSRV
|
||||
toolchain: 1.46.0 # MSRV
|
||||
components: clippy
|
||||
- run: sudo apt-get install libpcsclite-dev
|
||||
- run: cargo clippy --all --exclude crypto_box --all-features -- -D warnings
|
||||
|
||||
@@ -3,7 +3,7 @@ on:
|
||||
pull_request:
|
||||
paths: Cargo.lock
|
||||
push:
|
||||
branches: develop
|
||||
branches: main
|
||||
paths: Cargo.lock
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
+15
-1
@@ -4,7 +4,21 @@ 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.1.0 (2020-10-18)
|
||||
## 0.2.0 (2021-01-30)
|
||||
### Changed
|
||||
- Bump `der-parser` to v5.0 ([#194])
|
||||
- Improve self-signed certificates ([#207])
|
||||
- Bump `x509-parser` to v0.9 ([#208])
|
||||
- Bump elliptic-curve to 0.8. Also requires bumping p256 and p384 ([#208])
|
||||
- Bump MSRV to 1.46+ ([#208])
|
||||
- Bump `pbkdf2` dependency to v0.7 ([#219])
|
||||
|
||||
[#194]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/194
|
||||
[#207]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/207
|
||||
[#208]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/208
|
||||
[#219]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/219
|
||||
|
||||
## 0.1.0 (2020-10-19)
|
||||
### Added
|
||||
- `Certificate::generate_self_signed` ([#80])
|
||||
- `YubiKey::open_by_serial` ([#69])
|
||||
|
||||
Generated
+227
-264
File diff suppressed because it is too large
Load Diff
+10
-10
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "yubikey-piv"
|
||||
version = "0.1.0" # Also update html_root_url in lib.rs when bumping this
|
||||
version = "0.2.0" # Also update html_root_url in lib.rs when bumping this
|
||||
description = """
|
||||
Pure Rust host-side driver for the YubiKey Personal Identity Verification (PIV)
|
||||
application providing general-purpose public-key signing and encryption
|
||||
@@ -24,19 +24,19 @@ maintenance = { status = "experimental" }
|
||||
[dependencies]
|
||||
chrono = "0.4"
|
||||
cookie-factory = "0.3"
|
||||
der-parser = "4"
|
||||
der-parser = "5"
|
||||
des = "0.6"
|
||||
elliptic-curve = "0.6"
|
||||
elliptic-curve = "0.8"
|
||||
getrandom = "0.1"
|
||||
hmac = "0.10"
|
||||
log = "0.4"
|
||||
nom = "5"
|
||||
nom = "6"
|
||||
num-bigint = { version = "0.6", features = ["rand"], package = "num-bigint-dig" }
|
||||
num-traits = "0.2"
|
||||
num-integer = "0.1"
|
||||
pbkdf2 = "0.6"
|
||||
p256 = "0.5"
|
||||
p384 = "0.4"
|
||||
pbkdf2 = { version = "0.7", default-features = false }
|
||||
p256 = "0.7"
|
||||
p384 = "0.6"
|
||||
pcsc = "2"
|
||||
rsa = "0.3"
|
||||
secrecy = "0.7"
|
||||
@@ -44,13 +44,13 @@ sha-1 = "0.9"
|
||||
sha2 = "0.9"
|
||||
subtle = "2"
|
||||
subtle-encoding = "0.5"
|
||||
x509 = "0.1.2"
|
||||
x509-parser = "0.8"
|
||||
x509 = "0.2"
|
||||
x509-parser = "0.9"
|
||||
zeroize = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.8"
|
||||
ring = "0.16.15"
|
||||
ring = "0.16.18"
|
||||
lazy_static = "1"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<img src="https://raw.githubusercontent.com/iqlusioninc/yubikey-piv.rs/develop/img/logo.png" width="150" height="110">
|
||||
<img src="https://raw.githubusercontent.com/iqlusioninc/yubikey-piv.rs/main/img/logo.png" width="150" height="110">
|
||||
|
||||
# yubikey-piv.rs
|
||||
|
||||
@@ -36,7 +36,7 @@ endorsed by Yubico.
|
||||
|
||||
## Minimum Supported Rust Version
|
||||
|
||||
- Rust **1.44** or newer
|
||||
- Rust **1.46** or newer
|
||||
|
||||
## Supported YubiKeys
|
||||
|
||||
@@ -193,12 +193,12 @@ or conditions.
|
||||
[docs-image]: https://docs.rs/yubikey-piv/badge.svg
|
||||
[docs-link]: https://docs.rs/yubikey-piv/
|
||||
[license-image]: https://img.shields.io/badge/license-BSD-blue.svg
|
||||
[license-link]: https://github.com/iqlusioninc/yubikey-piv.rs/blob/develop/COPYING
|
||||
[rustc-image]: https://img.shields.io/badge/rustc-1.44+-blue.svg
|
||||
[license-link]: https://github.com/iqlusioninc/yubikey-piv.rs/blob/main/COPYING
|
||||
[rustc-image]: https://img.shields.io/badge/rustc-1.46+-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/
|
||||
[build-image]: https://github.com/iqlusioninc/yubikey-piv.rs/workflows/CI/badge.svg?branch=develop&event=push
|
||||
[build-image]: https://github.com/iqlusioninc/yubikey-piv.rs/workflows/CI/badge.svg?branch=main&event=push
|
||||
[build-link]: https://github.com/iqlusioninc/yubikey-piv.rs/actions
|
||||
[gitter-image]: https://badges.gitter.im/badge.svg
|
||||
[gitter-link]: https://gitter.im/iqlusioninc/community
|
||||
@@ -214,7 +214,7 @@ or conditions.
|
||||
[yubico-piv-tool]: https://github.com/Yubico/yubico-piv-tool/
|
||||
[Corrode]: https://github.com/jameysharp/corrode
|
||||
[cc-web]: https://contributor-covenant.org/
|
||||
[cc-md]: https://github.com/iqlusioninc/yubikey-piv.rs/blob/develop/CODE_OF_CONDUCT.md
|
||||
[cc-md]: https://github.com/iqlusioninc/yubikey-piv.rs/blob/main/CODE_OF_CONDUCT.md
|
||||
[BSDL]: https://opensource.org/licenses/BSD-2-Clause
|
||||
|
||||
[//]: # (github issues)
|
||||
|
||||
@@ -4,5 +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.1.0 (2020-10-19)
|
||||
### Added
|
||||
- `status` command ([#72], [#74])
|
||||
|
||||
### Changed
|
||||
- Bump `yubikey-piv` to v0.1.0 ([#180])
|
||||
- Bump `x509-parser` to v0.8 ([#181])
|
||||
- Bump `sha2` to v0.9 ([#182])
|
||||
- Rename `list` command to `readers`; improve usage ([#71])
|
||||
|
||||
[#182]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/182
|
||||
[#181]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/181
|
||||
[#180]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/180
|
||||
[#74]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/74
|
||||
[#72]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/72
|
||||
[#71]: https://github.com/iqlusioninc/yubikey-piv.rs/pull/71
|
||||
|
||||
## 0.0.1 (2019-12-02)
|
||||
- Initial release
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "yubikey-cli"
|
||||
version = "0.0.1"
|
||||
version = "0.1.0"
|
||||
description = """
|
||||
Command-line interface for performing encryption and signing using RSA/ECC keys
|
||||
stored on YubiKey devices.
|
||||
@@ -18,8 +18,8 @@ gumdrop = "0.8"
|
||||
env_logger = "0.8"
|
||||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
sha2 = "0.8"
|
||||
sha2 = "0.9"
|
||||
subtle-encoding = "0.5"
|
||||
termcolor = "1"
|
||||
x509-parser = "0.7"
|
||||
yubikey-piv = { version = "0.1", path = ".." }
|
||||
x509-parser = "0.9"
|
||||
yubikey-piv = { version = "0.2", path = ".." }
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
<img src="https://raw.githubusercontent.com/iqlusioninc/yubikey-piv.rs/develop/img/logo.png" width="150" height="110">
|
||||
<img src="https://raw.githubusercontent.com/iqlusioninc/yubikey-piv.rs/main/img/logo.png" width="150" height="110">
|
||||
|
||||
# yubikey-cli.rs
|
||||
|
||||
@@ -92,7 +92,7 @@ or conditions.
|
||||
[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/
|
||||
[build-image]: https://github.com/iqlusioninc/yubikey-piv.rs/workflows/Rust/badge.svg?branch=develop&event=push
|
||||
[build-image]: https://github.com/iqlusioninc/yubikey-piv.rs/workflows/CI/badge.svg?branch=main&event=push
|
||||
[build-link]: https://github.com/iqlusioninc/yubikey-piv.rs/actions
|
||||
[gitter-image]: https://badges.gitter.im/badge.svg
|
||||
[gitter-link]: https://gitter.im/iqlusioninc/community
|
||||
@@ -108,5 +108,5 @@ or conditions.
|
||||
[yubico-piv-tool]: https://github.com/Yubico/yubico-piv-tool/
|
||||
[Corrode]: https://github.com/jameysharp/corrode
|
||||
[cc-web]: https://contributor-covenant.org/
|
||||
[cc-md]: https://github.com/iqlusioninc/yubikey-cli.rs/blob/develop/CODE_OF_CONDUCT.md
|
||||
[cc-md]: https://github.com/iqlusioninc/yubikey-cli.rs/blob/main/CODE_OF_CONDUCT.md
|
||||
[BSDL]: https://opensource.org/licenses/BSD-2-Clause
|
||||
|
||||
+4
-4
@@ -19,7 +19,7 @@ use std::io::{self, Write};
|
||||
use std::str;
|
||||
use subtle_encoding::hex;
|
||||
use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
|
||||
use x509_parser::parse_x509_der;
|
||||
use x509_parser::parse_x509_certificate;
|
||||
use yubikey_piv::{certificate::Certificate, key::*, YubiKey};
|
||||
|
||||
///Write information about certificate found in slot a la yubico-piv-tool output.
|
||||
@@ -41,7 +41,7 @@ pub fn print_cert_info(
|
||||
let fingerprint = Sha256::digest(&buf);
|
||||
let slot_id: u8 = slot.into();
|
||||
print_cert_attr(stream, "Slot", format!("{:x}", slot_id))?;
|
||||
match parse_x509_der(&buf) {
|
||||
match parse_x509_certificate(&buf) {
|
||||
Ok((_rem, cert)) => {
|
||||
print_cert_attr(
|
||||
stream,
|
||||
@@ -59,12 +59,12 @@ pub fn print_cert_info(
|
||||
print_cert_attr(
|
||||
stream,
|
||||
"Not Before",
|
||||
cert.tbs_certificate.validity.not_before.asctime(),
|
||||
cert.tbs_certificate.validity.not_before.to_rfc2822(),
|
||||
)?;
|
||||
print_cert_attr(
|
||||
stream,
|
||||
"Not After",
|
||||
cert.tbs_certificate.validity.not_after.asctime(),
|
||||
cert.tbs_certificate.validity.not_after.to_rfc2822(),
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
|
||||
+30
-15
@@ -49,7 +49,8 @@ use sha2::{Digest, Sha256};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::ops::DerefMut;
|
||||
use x509_parser::{parse_x509_der, x509::SubjectPublicKeyInfo};
|
||||
use x509::{der::Oid, RelativeDistinguishedName};
|
||||
use x509_parser::{parse_x509_certificate, x509::SubjectPublicKeyInfo};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use crate::CB_OBJ_MAX;
|
||||
@@ -205,7 +206,13 @@ impl PublicKeyInfo {
|
||||
}
|
||||
OID_EC_PUBLIC_KEY => {
|
||||
let key_bytes = &subject_pki.subject_public_key.data;
|
||||
match read_pki::ec_parameters(&subject_pki.algorithm.parameters)? {
|
||||
let algorithm_parameters = subject_pki
|
||||
.algorithm
|
||||
.parameters
|
||||
.as_ref()
|
||||
.ok_or(Error::InvalidObject)?;
|
||||
|
||||
match read_pki::ec_parameters(algorithm_parameters)? {
|
||||
AlgorithmId::EccP256 => EcPublicKey::from_bytes(key_bytes)
|
||||
.map(PublicKeyInfo::EcP256)
|
||||
.map_err(|_| Error::InvalidObject),
|
||||
@@ -331,19 +338,21 @@ impl<'a> TryFrom<&'a [u8]> for Certificate {
|
||||
impl Certificate {
|
||||
/// Creates a new self-signed certificate for the given key. Writes the resulting
|
||||
/// certificate to the slot before returning it.
|
||||
pub fn generate_self_signed(
|
||||
///
|
||||
/// `extensions` is optional; if empty, no extensions will be included. Due to the
|
||||
/// need for an `O: Oid` type parameter, users who do not have any extensions should
|
||||
/// use the workaround `let extensions: &[x509::Extension<'_, &[u64]>] = &[];`.
|
||||
pub fn generate_self_signed<O: Oid>(
|
||||
yubikey: &mut YubiKey,
|
||||
key: SlotId,
|
||||
serial: impl Into<Serial>,
|
||||
not_after: Option<DateTime<Utc>>,
|
||||
subject: String,
|
||||
subject: &[RelativeDistinguishedName<'_>],
|
||||
subject_pki: PublicKeyInfo,
|
||||
extensions: &[x509::Extension<'_, O>],
|
||||
) -> Result<Self, Error> {
|
||||
let serial = serial.into();
|
||||
|
||||
// Issuer and subject are the same in self-signed certificates
|
||||
let issuer = subject.clone();
|
||||
|
||||
let mut tbs_cert = Buffer::new(Vec::with_capacity(CB_OBJ_MAX));
|
||||
|
||||
let signature_algorithm = match subject_pki.algorithm() {
|
||||
@@ -355,11 +364,13 @@ impl Certificate {
|
||||
x509::write::tbs_certificate(
|
||||
&serial.to_bytes(),
|
||||
&signature_algorithm,
|
||||
&issuer,
|
||||
// Issuer and subject are the same in self-signed certificates.
|
||||
&subject,
|
||||
Utc::now(),
|
||||
not_after,
|
||||
&subject,
|
||||
&subject_pki,
|
||||
&extensions,
|
||||
),
|
||||
tbs_cert.deref_mut(),
|
||||
)
|
||||
@@ -419,6 +430,15 @@ impl Certificate {
|
||||
)
|
||||
.expect("can serialize to Vec");
|
||||
|
||||
let (issuer, subject) = parse_x509_certificate(&data)
|
||||
.map(|(_, cert)| {
|
||||
(
|
||||
cert.tbs_certificate.issuer.to_string(),
|
||||
cert.tbs_certificate.subject.to_string(),
|
||||
)
|
||||
})
|
||||
.expect("We just serialized this correctly");
|
||||
|
||||
let cert = Certificate {
|
||||
serial,
|
||||
issuer,
|
||||
@@ -471,7 +491,7 @@ impl Certificate {
|
||||
return Err(Error::SizeError);
|
||||
}
|
||||
|
||||
let parsed_cert = match parse_x509_der(&cert) {
|
||||
let parsed_cert = match parse_x509_certificate(&cert) {
|
||||
Ok((_, cert)) => cert,
|
||||
_ => return Err(Error::InvalidObject),
|
||||
};
|
||||
@@ -631,12 +651,7 @@ mod read_pki {
|
||||
/// }
|
||||
/// ```
|
||||
pub(super) fn ec_parameters(parameters: &DerObject<'_>) -> Result<AlgorithmId, Error> {
|
||||
let curve_oid = match parameters.as_context_specific() {
|
||||
Ok((_, Some(named_curve))) => {
|
||||
named_curve.as_oid_val().map_err(|_| Error::InvalidObject)
|
||||
}
|
||||
_ => Err(Error::InvalidObject),
|
||||
}?;
|
||||
let curve_oid = parameters.as_oid_val().map_err(|_| Error::InvalidObject)?;
|
||||
|
||||
match curve_oid.to_string().as_str() {
|
||||
OID_NIST_P256 => Ok(AlgorithmId::EccP256),
|
||||
|
||||
+3
-3
@@ -83,12 +83,12 @@
|
||||
//! [YubiKey NEO]: https://support.yubico.com/support/solutions/articles/15000006494-yubikey-neo
|
||||
//! [YubiKey 4]: https://support.yubico.com/support/solutions/articles/15000006486-yubikey-4
|
||||
//! [YubiKey 5]: https://www.yubico.com/products/yubikey-5-overview/
|
||||
//! [status]: https://github.com/tarcieri/yubikey-piv.rs#status
|
||||
//! [status]: https://github.com/iqlusioninc/yubikey-piv.rs#status
|
||||
//! [yubico-piv-tool]: https://github.com/Yubico/yubico-piv-tool/
|
||||
//! [Corrode]: https://github.com/jameysharp/corrode
|
||||
//! [piv-tool-guide]: https://www.yubico.com/wp-content/uploads/2016/05/Yubico_PIV_Tool_Command_Line_Guide_en.pdf
|
||||
//! [cc-web]: https://contributor-covenant.org/
|
||||
//! [cc-md]: https://github.com/tarcieri/yubikey-piv.rs/blob/develop/CODE_OF_CONDUCT.md
|
||||
//! [cc-md]: https://github.com/iqlusioninc/yubikey-piv.rs/blob/main/CODE_OF_CONDUCT.md
|
||||
//! [BSDL]: https://opensource.org/licenses/BSD-2-Clause
|
||||
|
||||
// Adapted from yubico-piv-tool:
|
||||
@@ -122,7 +122,7 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#![doc(
|
||||
html_logo_url = "https://raw.githubusercontent.com/iqlusioninc/yubikey-piv.rs/develop/img/logo.png",
|
||||
html_logo_url = "https://raw.githubusercontent.com/iqlusioninc/yubikey-piv.rs/main/img/logo.png",
|
||||
html_root_url = "https://docs.rs/yubikey-piv/0.1.0"
|
||||
)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
@@ -10,6 +10,7 @@ use rsa::{hash::Hash::SHA2_256, PaddingScheme, PublicKey};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::convert::TryInto;
|
||||
use std::{env, sync::Mutex};
|
||||
use x509::RelativeDistinguishedName;
|
||||
use yubikey_piv::{
|
||||
certificate::{Certificate, PublicKeyInfo},
|
||||
key::{self, AlgorithmId, Key, RetiredSlotId, SlotId},
|
||||
@@ -132,13 +133,15 @@ fn generate_self_signed_cert(algorithm: AlgorithmId) -> Certificate {
|
||||
getrandom(&mut serial).unwrap();
|
||||
|
||||
// Generate a self-signed certificate for the new key.
|
||||
let extensions: &[x509::Extension<'_, &[u64]>] = &[];
|
||||
let cert_result = Certificate::generate_self_signed(
|
||||
&mut yubikey,
|
||||
slot,
|
||||
serial,
|
||||
None,
|
||||
"testSubject".to_owned(),
|
||||
&[RelativeDistinguishedName::common_name("testSubject")],
|
||||
generated,
|
||||
extensions,
|
||||
);
|
||||
|
||||
assert!(cert_result.is_ok());
|
||||
|
||||
Reference in New Issue
Block a user