From e841ba33315ea7d9044da6109300fabb8821296b Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Wed, 6 Apr 2022 00:33:40 +0800 Subject: [PATCH] feat: pgp card make --- src/cmd_pgpcardmake.rs | 117 ++++++++++++++++++++++++++++++++++++++--- src/main.rs | 1 - 2 files changed, 111 insertions(+), 7 deletions(-) diff --git a/src/cmd_pgpcardmake.rs b/src/cmd_pgpcardmake.rs index 9697001..243ea98 100644 --- a/src/cmd_pgpcardmake.rs +++ b/src/cmd_pgpcardmake.rs @@ -1,3 +1,5 @@ +use std::time::SystemTime; + use clap::{App, Arg, ArgMatches, SubCommand}; use openpgp::crypto::mpi::ProtectedMPI; use openpgp::crypto::mpi::PublicKey as MpiPublicKey; @@ -11,7 +13,9 @@ use openpgp::packet::key::SubordinateRole; use openpgp::packet::Signature; use openpgp::packet::signature::subpacket::{SubpacketTag, SubpacketValue}; use openpgp::parse::{PacketParser, PacketParserResult, Parse}; -use openpgp_card::OpenPgp; +use openpgp_card::{Error, KeyType, OpenPgp}; +use openpgp_card::card_do::KeyGenerationTime; +use openpgp_card::crypto_data::{CardUploadableKey, PrivateKeyMaterial, RSAKey}; use openssl::bn::BigNum; use rust_util::util_clap::{Command, CommandError}; use rust_util::XResult; @@ -38,11 +42,85 @@ impl PgpRsaPrivateKeySet { #[derive(Debug)] struct PgpRsaPrivateKey { + creation_time_secs: u32, key_id: KeyID, fingerprint: Fingerprint, rsa_private_key: RsaCrt, } +#[derive(Debug)] +struct RsaKeyCrt { + e: Vec, + p: Vec, + q: Vec, + pq: Vec, + dp1: Vec, + dq1: Vec, + n: Vec, +} + +impl RsaKeyCrt { + fn from(rsa_crt: &RsaCrt) -> Self { + Self { + e: rsa_crt.public_exponent.to_vec(), + p: rsa_crt.prime1.to_vec(), + q: rsa_crt.prime2.to_vec(), + pq: rsa_crt.coefficient.to_vec(), + dp1: rsa_crt.exponent1.to_vec(), + dq1: rsa_crt.exponent2.to_vec(), + n: rsa_crt.modulus.to_vec(), + } + } +} + +impl RSAKey for RsaKeyCrt { + fn e(&self) -> &[u8] { + self.e.as_slice() + } + + fn p(&self) -> &[u8] { + self.p.as_slice() + } + + fn q(&self) -> &[u8] { + self.q.as_slice() + } + + fn pq(&self) -> Box<[u8]> { + self.pq.clone().into() + } + + fn dp1(&self) -> Box<[u8]> { + self.dp1.clone().into() + } + + fn dq1(&self) -> Box<[u8]> { + self.dq1.clone().into() + } + + fn n(&self) -> &[u8] { + self.n.as_slice() + } +} + +impl CardUploadableKey for PgpRsaPrivateKey { + fn private_key(&self) -> Result { + Ok(PrivateKeyMaterial::R(Box::new(RsaKeyCrt::from(&self.rsa_private_key)))) + } + + fn timestamp(&self) -> KeyGenerationTime { + KeyGenerationTime::from(self.creation_time_secs) + } + + fn fingerprint(&self) -> Result { + if let Fingerprint::V4(fingerprint_v4) = self.fingerprint { + Ok(openpgp_card::card_do::Fingerprint::from(fingerprint_v4)) + } else { + Err(Error::InternalError("Not supported fingerprint version".to_string())) + } + } +} + pub struct CommandImpl; impl Command for CommandImpl { @@ -50,7 +128,7 @@ impl Command for CommandImpl { fn subcommand<'a>(&self) -> App<'a, 'a> { SubCommand::with_name(self.name()).about("OpenPGP Card Make subcommand") - // .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("12345678").help("OpenPGP card admin pin")) + .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("12345678").help("OpenPGP card admin pin")) .arg(Arg::with_name("pass").long("pass").takes_value(true).required(false).help("Password for PGP secret key")) .arg(Arg::with_name("in").long("in").takes_value(true).required(false).help("PGP file in")) .arg(Arg::with_name("force-make").long("force-make").help("Force make OpenPGP card")) @@ -103,10 +181,14 @@ impl Command for CommandImpl { } debugging!("Found PGP RSA private key set: {:?}", pgp_rsa_private_key_set); + success!("Found PGP RSA private keys, signing: {}, encryption: {}, authentication: {}", + pgp_rsa_private_key_set.signing.is_some(), + pgp_rsa_private_key_set.encryption.is_some(), + pgp_rsa_private_key_set.authentication.is_some()); - // TODO success logging if pgp_rsa_private_key_set.signing.is_none() || pgp_rsa_private_key_set.encryption.is_none() || pgp_rsa_private_key_set.authentication.is_none() { - warning!("");// TODO ... + warning!("PGP RSA private keys is not complete!"); + return Ok(None); } let force_make = sub_arg_matches.is_present("force-make"); @@ -123,7 +205,23 @@ impl Command for CommandImpl { opt_result!(trans.verify_pw3(pin.as_ref()), "Admin pin verify failed: {}"); success!("Admin pin verify success!"); - // trans.key_import() + let signing_key = pgp_rsa_private_key_set.signing.unwrap(); + let signing_key_id = signing_key.key_id.clone(); + information!("Prepare write PGP signing key, key id: {}", signing_key_id); + opt_result!(trans.key_import(Box::new(signing_key), KeyType::Signing), "Write PGP signing key failed: {}"); + success!("Write PGP signing key success, key id: {}", signing_key_id); + + let encryption_key = pgp_rsa_private_key_set.encryption.unwrap(); + let encryption_key_id = encryption_key.key_id.clone(); + information!("Prepare write PGP encryption key, key id: {}", signing_key_id); + opt_result!(trans.key_import(Box::new(encryption_key), KeyType::Decryption), "Write PGP encryption key failed: {}"); + success!("Write PGP encryption key success, key id: {}", encryption_key_id); + + let authentication_key = pgp_rsa_private_key_set.authentication.unwrap(); + let authentication_key_id = authentication_key.key_id.clone(); + information!("Prepare write PGP authentication key, key id: {}", signing_key_id); + opt_result!(trans.key_import(Box::new(authentication_key), KeyType::Authentication), "Write PGP authentication key failed: {}"); + success!("Write PGP authentication key success, key id: {}", authentication_key_id); Ok(None) } @@ -137,7 +235,12 @@ fn parse_security_sub_key_to_pgp_rsa_private_key(key: &Key