feat: update pkcs11 piv
This commit is contained in:
@@ -15,8 +15,11 @@ p256 = { version = "0.13.2", default-features = false, features = [
|
||||
"pkcs8",
|
||||
"std",
|
||||
] }
|
||||
pinentry = "0.5.0"
|
||||
rand = "0.8.5"
|
||||
rpassword = "7.3.1"
|
||||
rsa = { version = "0.9.6", default-features = false, features = ["std"] }
|
||||
secrecy = "0.8.0"
|
||||
# TODO: temporary workaround for RustCrypto/traits#1262, remove after upgrading
|
||||
# the p256 package past 0.13.0.
|
||||
spki = { version = "0.7.3", features = ["std"] }
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use tracing::instrument;
|
||||
use yubikey::YubiKey;
|
||||
@@ -27,14 +27,49 @@ use native_pkcs11_traits::Result as P11Result;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct YubikeyPivBackend {
|
||||
yubikey: Option<YubiKey>,
|
||||
cached_pin: Mutex<Option<String>>,
|
||||
yubikey: Mutex<Option<YubiKey>>,
|
||||
}
|
||||
|
||||
impl YubikeyPivBackend {
|
||||
pub fn new() -> Self {
|
||||
YubikeyPivBackend {
|
||||
yubikey: None
|
||||
YubikeyPivBackend::default()
|
||||
}
|
||||
|
||||
fn run_with_yubikey<F>(&self, verify: bool, mut callback: F) -> P11Result<()>
|
||||
where
|
||||
F: FnMut(&mut YubiKey) -> P11Result<()>,
|
||||
{
|
||||
let mut yubikey = self.yubikey.lock().unwrap();
|
||||
if yubikey.is_none() {
|
||||
*yubikey = Some(YubiKey::open()?);
|
||||
}
|
||||
let mut yk = yubikey.as_mut().unwrap();
|
||||
if verify {
|
||||
let pin = self.prepare_pin()?;
|
||||
let verify_result = yk.verify_pin(pin.as_bytes());
|
||||
if verify_result.is_err() {
|
||||
self.clear_pin();
|
||||
}
|
||||
verify_result?;
|
||||
}
|
||||
callback(&mut yk)
|
||||
}
|
||||
|
||||
fn clear_pin(&self) -> () {
|
||||
let mut cached_pin = self.cached_pin.lock().unwrap();
|
||||
if cached_pin.is_some() {
|
||||
*cached_pin = None;
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_pin(&self) -> P11Result<String> {
|
||||
let mut cached_pin = self.cached_pin.lock().unwrap();
|
||||
if cached_pin.is_none() {
|
||||
let pin = crate::piv::pinentry::get_pin()?;
|
||||
*cached_pin = Some(pin);
|
||||
}
|
||||
Ok(cached_pin.as_deref().unwrap().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ use native_pkcs11_traits::SignatureAlgorithm;
|
||||
mod backend;
|
||||
pub mod certificate;
|
||||
pub mod key;
|
||||
mod pinentry;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
|
||||
51
native-pkcs11-piv/src/piv/pinentry.rs
Normal file
51
native-pkcs11-piv/src/piv/pinentry.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
use std::{env, fs};
|
||||
|
||||
use pinentry::PassphraseInput;
|
||||
use secrecy::ExposeSecret;
|
||||
|
||||
const PIN_ENTRY_ENV: &str = "PIN_ENTRY_CMD";
|
||||
const PIN_ENTRY_1: &str = "/usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac";
|
||||
const PIN_ENTRY_DEFAULT: &str = "pinentry";
|
||||
|
||||
pub fn get_pin() -> Result<String, String> {
|
||||
let pin_entry = get_pin_entry();
|
||||
let description = "Please input PIN";
|
||||
let prompt = "PIN: ";
|
||||
|
||||
if let Some(mut input) = PassphraseInput::with_binary(pin_entry) {
|
||||
let secret = input
|
||||
.with_description(&format!("{}.", description))
|
||||
.with_prompt(prompt)
|
||||
.interact();
|
||||
|
||||
match secret {
|
||||
Ok(secret_string) => {
|
||||
Ok(secret_string.expose_secret().to_string())
|
||||
}
|
||||
Err(e) => {
|
||||
Err(format!("Read PIN failed: {}", e))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match rpassword::prompt_password(format!("{}: ", description)) {
|
||||
Ok(pin) => {
|
||||
Ok(pin)
|
||||
}
|
||||
Err(e) => {
|
||||
Err(format!("Read PIN2 failed: {}", e))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pin_entry() -> String {
|
||||
if let Ok(pin_entry) = env::var(PIN_ENTRY_ENV) {
|
||||
return pin_entry;
|
||||
}
|
||||
if let Ok(m) = fs::metadata(PIN_ENTRY_1) {
|
||||
if m.is_file() {
|
||||
return PIN_ENTRY_1.to_string();
|
||||
}
|
||||
}
|
||||
PIN_ENTRY_DEFAULT.to_string()
|
||||
}
|
||||
Reference in New Issue
Block a user