opgpcard: Add optional user-id parameter for "pubkey" and "admin generate", to bind User IDs to the certificate.

This commit is contained in:
Heiko Schaefer 2022-09-04 18:14:38 +02:00
parent 8e6f03a2c5
commit 96e28b1b4f
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
4 changed files with 53 additions and 12 deletions

View file

@ -276,6 +276,7 @@ pub fn test_keygen(
Some(b"123456"),
&|| {},
&|| {},
&[],
)?;
let armored = String::from_utf8(cert.armored().to_vec()?)?;

View file

@ -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())?;

View file

@ -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

View file

@ -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()?)?;