Bump MSRV to 1.81 (#582)
This is required due to the `hybrid-array` crate, which has become a transitive dependency of the majority of our dependencies and will be required in the very near future.
This commit is contained in:
@@ -36,13 +36,13 @@ jobs:
|
|||||||
toolchain: stable
|
toolchain: stable
|
||||||
deps: true
|
deps: true
|
||||||
- platform: ubuntu-latest
|
- platform: ubuntu-latest
|
||||||
toolchain: 1.74.0 # MSRV
|
toolchain: 1.81.0 # MSRV
|
||||||
deps: sudo apt-get install libpcsclite-dev
|
deps: sudo apt-get install libpcsclite-dev
|
||||||
- platform: windows-latest
|
- platform: windows-latest
|
||||||
toolchain: 1.74.0 # MSRV
|
toolchain: 1.81.0 # MSRV
|
||||||
deps: true
|
deps: true
|
||||||
- platform: macos-latest
|
- platform: macos-latest
|
||||||
toolchain: 1.74.0 # MSRV
|
toolchain: 1.81.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.74.0 # MSRV
|
toolchain: 1.81.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,10 @@ 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).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
### Changed
|
||||||
|
- MSRV is now 1.81.
|
||||||
|
|
||||||
## 0.8.0 (2023-08-15)
|
## 0.8.0 (2023-08-15)
|
||||||
### Added
|
### Added
|
||||||
- `impl Debug for {Context, YubiKey}` ([#457])
|
- `impl Debug for {Context, YubiKey}` ([#457])
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ readme = "README.md"
|
|||||||
categories = ["api-bindings", "authentication", "cryptography", "hardware-support"]
|
categories = ["api-bindings", "authentication", "cryptography", "hardware-support"]
|
||||||
keywords = ["ecdsa", "encryption", "rsa", "piv", "signature"]
|
keywords = ["ecdsa", "encryption", "rsa", "piv", "signature"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.65"
|
rust-version = "1.81"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [".", "cli"]
|
members = [".", "cli"]
|
||||||
|
|||||||
@@ -214,7 +214,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
|
||||||
[msrv-image]: https://img.shields.io/badge/rustc-1.65+-blue.svg
|
[msrv-image]: https://img.shields.io/badge/rustc-1.81+-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,10 @@ 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).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
### Changed
|
||||||
|
- MSRV is now 1.81.
|
||||||
|
|
||||||
## 0.7.0 (2022-11-14)
|
## 0.7.0 (2022-11-14)
|
||||||
### Changed
|
### Changed
|
||||||
- Bump `clap` to v4.0 ([#438])
|
- Bump `clap` to v4.0 ([#438])
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ 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"
|
edition = "2021"
|
||||||
rust-version = "1.56"
|
rust-version = "1.81"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
|
|||||||
+1
-1
@@ -196,7 +196,7 @@ pub fn print_cert_info(
|
|||||||
print_cert_attr(
|
print_cert_attr(
|
||||||
stream,
|
stream,
|
||||||
"Fingerprint",
|
"Fingerprint",
|
||||||
&hex::upper::encode_string(&fingerprint),
|
hex::upper::encode_string(&fingerprint),
|
||||||
)?;
|
)?;
|
||||||
print_cert_attr(
|
print_cert_attr(
|
||||||
stream,
|
stream,
|
||||||
|
|||||||
+2
-2
@@ -192,8 +192,8 @@ impl std::error::Error for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<x509_cert::der::Error> for Error {
|
impl From<der::Error> for Error {
|
||||||
fn from(_err: x509_cert::der::Error) -> Error {
|
fn from(_err: der::Error) -> Error {
|
||||||
Error::ParseError
|
Error::ParseError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-20
@@ -155,15 +155,12 @@ impl MgmKey {
|
|||||||
pub fn get_protected(yubikey: &mut YubiKey) -> Result<Self> {
|
pub fn get_protected(yubikey: &mut YubiKey) -> Result<Self> {
|
||||||
let txn = yubikey.begin_transaction()?;
|
let txn = yubikey.begin_transaction()?;
|
||||||
|
|
||||||
let protected_data = ProtectedData::read(&txn).map_err(|e| {
|
let protected_data = ProtectedData::read(&txn)
|
||||||
error!("could not read protected data (err: {:?})", e);
|
.inspect_err(|e| error!("could not read protected data (err: {:?})", e))?;
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let item = protected_data.get_item(TAG_PROTECTED_MGM).map_err(|e| {
|
let item = protected_data
|
||||||
error!("could not read protected MGM from metadata (err: {:?})", e);
|
.get_item(TAG_PROTECTED_MGM)
|
||||||
e
|
.inspect_err(|e| error!("could not read protected MGM from metadata (err: {:?})", e))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
if item.len() != DES_LEN_3DES {
|
if item.len() != DES_LEN_3DES {
|
||||||
error!(
|
error!(
|
||||||
@@ -196,12 +193,10 @@ 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)
|
||||||
// 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);
|
.inspect_err(|e| error!("could not set new derived mgm key, err = {}", e))?;
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// After this point, we've set the mgm key, so the function should succeed,
|
// After this point, we've set the mgm key, so the function should succeed,
|
||||||
// regardless of being able to set the metadata.
|
// regardless of being able to set the metadata.
|
||||||
@@ -255,12 +250,10 @@ impl MgmKey {
|
|||||||
pub fn set_protected(&self, yubikey: &mut YubiKey) -> Result<()> {
|
pub fn set_protected(&self, yubikey: &mut YubiKey) -> Result<()> {
|
||||||
let txn = yubikey.begin_transaction()?;
|
let txn = yubikey.begin_transaction()?;
|
||||||
|
|
||||||
txn.set_mgm_key(self, false).map_err(|e| {
|
txn.set_mgm_key(self, false)
|
||||||
// log a warning, since the device mgm key is corrupt or we're in
|
// log a warning, since the device mgm key is corrupt or we're in
|
||||||
// a state where we can't set the mgm key
|
// a state where we can't set the mgm key
|
||||||
error!("could not set new derived mgm key, err = {}", e);
|
.inspect_err(|e| error!("could not set new derived mgm key, err = {}", e))?;
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// after this point, we've set the mgm key, so the function should
|
// after this point, we've set the mgm key, so the function should
|
||||||
// succeed, regardless of being able to set the metadata
|
// succeed, regardless of being able to set the metadata
|
||||||
@@ -272,10 +265,9 @@ impl MgmKey {
|
|||||||
if let Err(e) = protected_data.set_item(TAG_PROTECTED_MGM, self.as_ref()) {
|
if let Err(e) = protected_data.set_item(TAG_PROTECTED_MGM, self.as_ref()) {
|
||||||
error!("could not set protected mgm item, err = {:?}", e);
|
error!("could not set protected mgm item, err = {:?}", e);
|
||||||
} else {
|
} else {
|
||||||
protected_data.write(&txn).map_err(|e| {
|
protected_data
|
||||||
error!("could not write protected data, err = {:?}", e);
|
.write(&txn)
|
||||||
e
|
.inspect_err(|e| error!("could not write protected data, err = {:?}", e))?;
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the protected mgm flag in admin data
|
// set the protected mgm flag in admin data
|
||||||
|
|||||||
+3
-4
@@ -96,10 +96,9 @@ impl MsRoots {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MsRoots::new(&data).map(Some).map_err(|e| {
|
MsRoots::new(&data)
|
||||||
error!("error parsing msroots: {:?}", e);
|
.map(Some)
|
||||||
e
|
.inspect_err(|e| error!("error parsing msroots: {:?}", e))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write `msroots` file to YubiKey
|
/// Write `msroots` file to YubiKey
|
||||||
|
|||||||
+2
-8
@@ -66,10 +66,7 @@ impl<'tx> Transaction<'tx> {
|
|||||||
.p1(0x04)
|
.p1(0x04)
|
||||||
.data(piv::APPLET_ID)
|
.data(piv::APPLET_ID)
|
||||||
.transmit(self, 0xFF)
|
.transmit(self, 0xFF)
|
||||||
.map_err(|e| {
|
.inspect_err(|e| error!("failed communicating with card: '{}'", e))?;
|
||||||
error!("failed communicating with card: '{}'", e);
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if !response.is_success() {
|
if !response.is_success() {
|
||||||
error!(
|
error!(
|
||||||
@@ -335,10 +332,7 @@ impl<'tx> Transaction<'tx> {
|
|||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
.transfer_data(&templ, &indata[..offset], 1024)
|
.transfer_data(&templ, &indata[..offset], 1024)
|
||||||
.map_err(|e| {
|
.inspect_err(|e| error!("sign command failed to communicate: {}", e))?;
|
||||||
error!("sign command failed to communicate: {}", e);
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if !response.is_success() {
|
if !response.is_success() {
|
||||||
error!("failed sign command with code {:x}", response.code());
|
error!("failed sign command with code {:x}", response.code());
|
||||||
|
|||||||
+13
-17
@@ -42,7 +42,7 @@ use crate::{
|
|||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
};
|
};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use pcsc::{Card, Disposition};
|
use pcsc::Card;
|
||||||
use rand_core::{OsRng, RngCore};
|
use rand_core::{OsRng, RngCore};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
@@ -293,7 +293,10 @@ impl YubiKey {
|
|||||||
/// `YubiKey` implements `Drop` which automatically disconnects the card using
|
/// `YubiKey` implements `Drop` which automatically disconnects the card using
|
||||||
/// `Disposition::ResetCard`; you only need to call this function if you want to
|
/// `Disposition::ResetCard`; you only need to call this function if you want to
|
||||||
/// handle errors or use a different disposition method.
|
/// handle errors or use a different disposition method.
|
||||||
pub fn disconnect(self, disposition: Disposition) -> core::result::Result<(), (Self, Error)> {
|
pub fn disconnect(
|
||||||
|
self,
|
||||||
|
disposition: pcsc::Disposition,
|
||||||
|
) -> core::result::Result<(), (Self, Error)> {
|
||||||
let Self {
|
let Self {
|
||||||
card,
|
card,
|
||||||
name,
|
name,
|
||||||
@@ -523,15 +526,11 @@ impl YubiKey {
|
|||||||
|
|
||||||
admin_data
|
admin_data
|
||||||
.set_item(TAG_ADMIN_TIMESTAMP, &tnow)
|
.set_item(TAG_ADMIN_TIMESTAMP, &tnow)
|
||||||
.map_err(|e| {
|
.inspect_err(|e| error!("could not set pin timestamp, err = {}", e))?;
|
||||||
error!("could not set pin timestamp, err = {}", e);
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
|
|
||||||
admin_data.write(&txn).map_err(|e| {
|
admin_data
|
||||||
error!("could not write admin data, err = {}", e);
|
.write(&txn)
|
||||||
e
|
.inspect_err(|e| error!("could not write admin data, err = {}", e))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -581,7 +580,7 @@ impl YubiKey {
|
|||||||
|
|
||||||
// Attempt to set the "PUK blocked" flag in admin data.
|
// Attempt to set the "PUK blocked" flag in admin data.
|
||||||
let mut admin_data = AdminData::read(&txn)
|
let mut admin_data = AdminData::read(&txn)
|
||||||
.map(|data| {
|
.inspect(|data| {
|
||||||
if let Ok(item) = data.get_item(TAG_ADMIN_FLAGS_1) {
|
if let Ok(item) = data.get_item(TAG_ADMIN_FLAGS_1) {
|
||||||
if item.len() == flags.len() {
|
if item.len() == flags.len() {
|
||||||
flags.copy_from_slice(item)
|
flags.copy_from_slice(item)
|
||||||
@@ -593,8 +592,6 @@ impl YubiKey {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data
|
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
@@ -703,10 +700,9 @@ impl<'a> TryFrom<&'a Reader<'_>> for YubiKey {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(reader: &'a Reader<'_>) -> Result<Self> {
|
fn try_from(reader: &'a Reader<'_>) -> Result<Self> {
|
||||||
let mut card = reader.connect().map_err(|e| {
|
let mut card = reader
|
||||||
error!("error connecting to reader '{}': {}", reader.name(), e);
|
.connect()
|
||||||
e
|
.inspect_err(|e| error!("error connecting to reader '{}': {}", reader.name(), e))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
info!("connected to reader: {}", reader.name());
|
info!("connected to reader: {}", reader.name());
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ use signature::hazmat::PrehashVerifier;
|
|||||||
use std::{env, str::FromStr, sync::Mutex, time::Duration};
|
use std::{env, str::FromStr, sync::Mutex, time::Duration};
|
||||||
use x509_cert::{der::Encode, name::Name, serial_number::SerialNumber, time::Validity};
|
use x509_cert::{der::Encode, name::Name, serial_number::SerialNumber, time::Validity};
|
||||||
use yubikey::{
|
use yubikey::{
|
||||||
certificate,
|
certificate::{yubikey_signer, Certificate},
|
||||||
certificate::yubikey_signer,
|
|
||||||
certificate::Certificate,
|
|
||||||
piv::{self, AlgorithmId, Key, ManagementSlotId, RetiredSlotId, SlotId},
|
piv::{self, AlgorithmId, Key, ManagementSlotId, RetiredSlotId, SlotId},
|
||||||
Error, MgmKey, PinPolicy, Serial, TouchPolicy, YubiKey,
|
Error, MgmKey, PinPolicy, Serial, TouchPolicy, YubiKey,
|
||||||
};
|
};
|
||||||
@@ -317,8 +315,7 @@ fn test_read_metadata() {
|
|||||||
#[ignore]
|
#[ignore]
|
||||||
fn test_parse_cert_from_der() {
|
fn test_parse_cert_from_der() {
|
||||||
let bob_der = std::fs::read("tests/assets/Bob.der").expect(".der file not found");
|
let bob_der = std::fs::read("tests/assets/Bob.der").expect(".der file not found");
|
||||||
let cert =
|
let cert = Certificate::from_bytes(bob_der).expect("Failed to parse valid certificate");
|
||||||
certificate::Certificate::from_bytes(bob_der).expect("Failed to parse valid certificate");
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cert.subject(),
|
cert.subject(),
|
||||||
"CN=Bob",
|
"CN=Bob",
|
||||||
|
|||||||
Reference in New Issue
Block a user