Request PIN before certificate generation if PIN policy is "always"
We also correctly ask for a PIN touch after the key is generated (which does not need it) but before certificate generation (which does if the touch policy is not "none"). Closes str4d/age-plugin-yubikey#101.
This commit is contained in:
@@ -20,6 +20,10 @@ to 0.3.0 are beta releases.
|
|||||||
`age-plugin-yubikey` won't request a PIN entry to decrypt a file with an
|
`age-plugin-yubikey` won't request a PIN entry to decrypt a file with an
|
||||||
identity that has a PIN policy of `once`.
|
identity that has a PIN policy of `once`.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Identities can now be generated with a PIN policy of "always" (in previous
|
||||||
|
versions of `age-plugin-yubikey` this would cause an error).
|
||||||
|
|
||||||
## [0.3.2] - 2023-01-01
|
## [0.3.2] - 2023-01-01
|
||||||
### Changed
|
### Changed
|
||||||
- The "sharing violation" logic now also sends SIGHUP to any `yubikey-agent`
|
- The "sharing violation" logic now also sends SIGHUP to any `yubikey-agent`
|
||||||
|
|||||||
@@ -144,6 +144,12 @@ mgr-changing-mgmt-key-error =
|
|||||||
{" "}{$management_key}
|
{" "}{$management_key}
|
||||||
mgr-changing-mgmt-key-success = Success!
|
mgr-changing-mgmt-key-success = Success!
|
||||||
|
|
||||||
|
## YubiKey keygen
|
||||||
|
|
||||||
|
builder-gen-key = 🎲 Generating key...
|
||||||
|
builder-gen-cert = 🔏 Generating certificate...
|
||||||
|
builder-touch-yk = 👆 Please touch the {-yubikey}
|
||||||
|
|
||||||
## Plugin usage
|
## Plugin usage
|
||||||
|
|
||||||
plugin-err-invalid-recipient = Invalid recipient
|
plugin-err-invalid-recipient = Invalid recipient
|
||||||
|
|||||||
+24
-6
@@ -1,3 +1,4 @@
|
|||||||
|
use dialoguer::Password;
|
||||||
use rand::{rngs::OsRng, RngCore};
|
use rand::{rngs::OsRng, RngCore};
|
||||||
use x509::RelativeDistinguishedName;
|
use x509::RelativeDistinguishedName;
|
||||||
use yubikey::{
|
use yubikey::{
|
||||||
@@ -8,6 +9,7 @@ use yubikey::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
|
fl,
|
||||||
key::{self, Stub},
|
key::{self, Stub},
|
||||||
p256::Recipient,
|
p256::Recipient,
|
||||||
util::{Metadata, POLICY_EXTENSION_OID},
|
util::{Metadata, POLICY_EXTENSION_OID},
|
||||||
@@ -86,17 +88,13 @@ impl IdentityBuilder {
|
|||||||
let pin_policy = self.pin_policy.unwrap_or(DEFAULT_PIN_POLICY);
|
let pin_policy = self.pin_policy.unwrap_or(DEFAULT_PIN_POLICY);
|
||||||
let touch_policy = self.touch_policy.unwrap_or(DEFAULT_TOUCH_POLICY);
|
let touch_policy = self.touch_policy.unwrap_or(DEFAULT_TOUCH_POLICY);
|
||||||
|
|
||||||
|
eprintln!("{}", fl!("builder-gen-key"));
|
||||||
|
|
||||||
// No need to ask for users to enter their PIN if the PIN policy requires it,
|
// No need to ask for users to enter their PIN if the PIN policy requires it,
|
||||||
// because here we _always_ require them to enter their PIN in order to access the
|
// because here we _always_ require them to enter their PIN in order to access the
|
||||||
// protected management key (which is necessary in order to generate identities).
|
// protected management key (which is necessary in order to generate identities).
|
||||||
key::manage(yubikey)?;
|
key::manage(yubikey)?;
|
||||||
|
|
||||||
if let TouchPolicy::Never = touch_policy {
|
|
||||||
// No need to touch YubiKey
|
|
||||||
} else {
|
|
||||||
eprintln!("👆 Please touch the YubiKey");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a new key in the selected slot.
|
// Generate a new key in the selected slot.
|
||||||
let generated = yubikey_generate(
|
let generated = yubikey_generate(
|
||||||
yubikey,
|
yubikey,
|
||||||
@@ -109,6 +107,9 @@ impl IdentityBuilder {
|
|||||||
let recipient = Recipient::from_spki(&generated).expect("YubiKey generates a valid pubkey");
|
let recipient = Recipient::from_spki(&generated).expect("YubiKey generates a valid pubkey");
|
||||||
let stub = Stub::new(yubikey.serial(), slot, &recipient);
|
let stub = Stub::new(yubikey.serial(), slot, &recipient);
|
||||||
|
|
||||||
|
eprintln!();
|
||||||
|
eprintln!("{}", fl!("builder-gen-cert"));
|
||||||
|
|
||||||
// Pick a random serial for the new self-signed certificate.
|
// Pick a random serial for the new self-signed certificate.
|
||||||
let mut serial = [0; 20];
|
let mut serial = [0; 20];
|
||||||
OsRng.fill_bytes(&mut serial);
|
OsRng.fill_bytes(&mut serial);
|
||||||
@@ -117,6 +118,23 @@ impl IdentityBuilder {
|
|||||||
.name
|
.name
|
||||||
.unwrap_or(format!("age identity {}", hex::encode(stub.tag)));
|
.unwrap_or(format!("age identity {}", hex::encode(stub.tag)));
|
||||||
|
|
||||||
|
if let PinPolicy::Always = pin_policy {
|
||||||
|
// We need to enter the PIN again.
|
||||||
|
let pin = Password::new()
|
||||||
|
.with_prompt(fl!(
|
||||||
|
"plugin-enter-pin",
|
||||||
|
yubikey_serial = yubikey.serial().to_string(),
|
||||||
|
))
|
||||||
|
.report(true)
|
||||||
|
.interact()?;
|
||||||
|
yubikey.verify_pin(pin.as_bytes())?;
|
||||||
|
}
|
||||||
|
if let TouchPolicy::Never = touch_policy {
|
||||||
|
// No need to touch YubiKey
|
||||||
|
} else {
|
||||||
|
eprintln!("{}", fl!("builder-touch-yk"));
|
||||||
|
}
|
||||||
|
|
||||||
let cert = Certificate::generate_self_signed(
|
let cert = Certificate::generate_self_signed(
|
||||||
yubikey,
|
yubikey,
|
||||||
SlotId::Retired(slot),
|
SlotId::Retired(slot),
|
||||||
|
|||||||
Reference in New Issue
Block a user