opgpcard: Add optional user-id parameter for "pubkey" and "admin generate", to bind User IDs to the certificate.
This commit is contained in:
parent
8e6f03a2c5
commit
96e28b1b4f
4 changed files with 53 additions and 12 deletions
|
@ -276,6 +276,7 @@ pub fn test_keygen(
|
|||
Some(b"123456"),
|
||||
&|| {},
|
||||
&|| {},
|
||||
&[],
|
||||
)?;
|
||||
let armored = String::from_utf8(cert.armored().to_vec()?)?;
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ use crate::PublicKey;
|
|||
/// `prompt` notifies the user when a pinpad needs the user pin as input.
|
||||
///
|
||||
/// FIXME: accept optional metadata for user_id(s)?
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn make_cert<'app>(
|
||||
open: &mut Open<'app>,
|
||||
key_sig: PublicKey,
|
||||
|
@ -53,6 +54,7 @@ pub fn make_cert<'app>(
|
|||
pw1: Option<&[u8]>,
|
||||
pinpad_prompt: &dyn Fn(),
|
||||
touch_prompt: &(dyn Fn() + Send + Sync),
|
||||
user_ids: &[String],
|
||||
) -> Result<Cert> {
|
||||
let mut pp = vec![];
|
||||
|
||||
|
@ -137,8 +139,12 @@ pub fn make_cert<'app>(
|
|||
|
||||
// FIXME: accept user id/email as argument?!
|
||||
|
||||
if let Some(name) = cardholder.name() {
|
||||
let uid: UserID = name.into();
|
||||
for uid in user_ids
|
||||
.iter()
|
||||
.map(|uid| uid.as_bytes())
|
||||
.chain(cardholder.name())
|
||||
{
|
||||
let uid: UserID = uid.into();
|
||||
|
||||
pp.push(uid.clone().into());
|
||||
|
||||
|
@ -161,7 +167,7 @@ pub fn make_cert<'app>(
|
|||
|
||||
if let Some(mut sign) = open.signing_card() {
|
||||
// Card-backed signer for bindings
|
||||
let mut card_signer = sign.signer_from_public(key_sig, touch_prompt);
|
||||
let mut card_signer = sign.signer_from_public(key_sig.clone(), touch_prompt);
|
||||
|
||||
// Temporary version of the cert
|
||||
let cert = Cert::try_from(pp.clone())?;
|
||||
|
|
|
@ -54,6 +54,10 @@ pub enum Command {
|
|||
|
||||
#[clap(name = "User PIN file", short = 'p', long = "user-pin")]
|
||||
user_pin: Option<PathBuf>,
|
||||
|
||||
/// User ID to add to the exported certificate representation
|
||||
#[clap(name = "User ID", short = 'u', long = "user-id")]
|
||||
user_id: Vec<String>,
|
||||
},
|
||||
|
||||
/// Administer data on a card (including keys and metadata)
|
||||
|
@ -175,6 +179,10 @@ pub enum AdminCommand {
|
|||
/// Algorithm (rsa2048|rsa3072|rsa4096|nistp256|nistp384|nistp521|25519)
|
||||
#[clap()]
|
||||
algo: Option<String>,
|
||||
|
||||
/// User ID to add to the exported certificate representation
|
||||
#[clap(name = "User ID", short = 'u', long = "user-id")]
|
||||
user_id: Vec<String>,
|
||||
},
|
||||
|
||||
/// Set touch policy
|
||||
|
|
|
@ -56,8 +56,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
cli::Command::Ssh { ident } => {
|
||||
print_ssh(ident)?;
|
||||
}
|
||||
cli::Command::Pubkey { ident, user_pin } => {
|
||||
print_pubkey(ident, user_pin)?;
|
||||
cli::Command::Pubkey {
|
||||
ident,
|
||||
user_pin,
|
||||
user_id,
|
||||
} => {
|
||||
print_pubkey(ident, user_pin, user_id)?;
|
||||
}
|
||||
cli::Command::SetIdentity { ident, id } => {
|
||||
set_identity(&ident, id)?;
|
||||
|
@ -300,6 +304,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
no_decrypt,
|
||||
no_auth,
|
||||
algo,
|
||||
user_id,
|
||||
} => {
|
||||
let user_pin = util::get_pin(&mut open, user_pin, ENTER_USER_PIN);
|
||||
|
||||
|
@ -311,6 +316,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
!no_decrypt,
|
||||
!no_auth,
|
||||
algo,
|
||||
user_id,
|
||||
)?;
|
||||
}
|
||||
cli::AdminCommand::Touch { key, policy } => {
|
||||
|
@ -902,7 +908,11 @@ fn print_ssh(ident: Option<String>) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn print_pubkey(ident: Option<String>, user_pin: Option<PathBuf>) -> Result<()> {
|
||||
fn print_pubkey(
|
||||
ident: Option<String>,
|
||||
user_pin: Option<PathBuf>,
|
||||
user_ids: Vec<String>,
|
||||
) -> Result<()> {
|
||||
let mut card = pick_card_for_reading(ident)?;
|
||||
|
||||
let mut pgp = OpenPgp::new(&mut *card);
|
||||
|
@ -956,6 +966,7 @@ fn print_pubkey(ident: Option<String>, user_pin: Option<PathBuf>) -> Result<()>
|
|||
key_dec,
|
||||
key_aut,
|
||||
user_pin.as_deref(),
|
||||
&user_ids,
|
||||
&|| println!("Enter User PIN on card reader pinpad."),
|
||||
)?;
|
||||
|
||||
|
@ -1061,6 +1072,7 @@ fn get_cert(
|
|||
key_dec: Option<PublicKey>,
|
||||
key_aut: Option<PublicKey>,
|
||||
user_pin: Option<&[u8]>,
|
||||
user_ids: &[String],
|
||||
prompt: &dyn Fn(),
|
||||
) -> Result<Cert> {
|
||||
if user_pin.is_none() && open.feature_pinpad_verify() {
|
||||
|
@ -1070,9 +1082,16 @@ fn get_cert(
|
|||
);
|
||||
}
|
||||
|
||||
make_cert(open, key_sig, key_dec, key_aut, user_pin, prompt, &|| {
|
||||
println!("Touch confirmation needed for signing")
|
||||
})
|
||||
make_cert(
|
||||
open,
|
||||
key_sig,
|
||||
key_dec,
|
||||
key_aut,
|
||||
user_pin,
|
||||
prompt,
|
||||
&|| println!("Touch confirmation needed for signing"),
|
||||
&user_ids,
|
||||
)
|
||||
}
|
||||
|
||||
fn generate_keys(
|
||||
|
@ -1083,6 +1102,7 @@ fn generate_keys(
|
|||
decrypt: bool,
|
||||
auth: bool,
|
||||
algo: Option<String>,
|
||||
user_ids: Vec<String>,
|
||||
) -> Result<()> {
|
||||
// 1) Interpret the user's choice of algorithm.
|
||||
//
|
||||
|
@ -1124,9 +1144,15 @@ fn generate_keys(
|
|||
// 3) Generate a Cert from the generated keys. For this, we
|
||||
// need "signing" access to the card (to make binding signatures within
|
||||
// the Cert).
|
||||
let cert = get_cert(&mut open, key_sig, key_dec, key_aut, user_pin, &|| {
|
||||
println!("Enter User PIN on card reader pinpad.")
|
||||
})?;
|
||||
let cert = get_cert(
|
||||
&mut open,
|
||||
key_sig,
|
||||
key_dec,
|
||||
key_aut,
|
||||
user_pin,
|
||||
&user_ids,
|
||||
&|| println!("Enter User PIN on card reader pinpad."),
|
||||
)?;
|
||||
|
||||
let armored = String::from_utf8(cert.armored().to_vec()?)?;
|
||||
|
||||
|
|
Loading…
Reference in a new issue