Move "make_cert" into openpgp-card-sequoia
This commit is contained in:
parent
f1add02672
commit
765b4e8fdc
2 changed files with 128 additions and 110 deletions
|
@ -9,9 +9,11 @@ use std::string::FromUtf8Error;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use sequoia_openpgp::packet::key::{KeyRole, PrimaryRole, SubordinateRole};
|
use sequoia_openpgp::packet::key::{
|
||||||
|
KeyRole, PrimaryRole, PublicParts, SubordinateRole, UnspecifiedRole,
|
||||||
|
};
|
||||||
use sequoia_openpgp::packet::signature::SignatureBuilder;
|
use sequoia_openpgp::packet::signature::SignatureBuilder;
|
||||||
use sequoia_openpgp::packet::UserID;
|
use sequoia_openpgp::packet::{Key, UserID};
|
||||||
use sequoia_openpgp::parse::Parse;
|
use sequoia_openpgp::parse::Parse;
|
||||||
use sequoia_openpgp::serialize::SerializeInto;
|
use sequoia_openpgp::serialize::SerializeInto;
|
||||||
use sequoia_openpgp::types::{KeyFlags, SignatureType, Timestamp};
|
use sequoia_openpgp::types::{KeyFlags, SignatureType, Timestamp};
|
||||||
|
@ -22,7 +24,7 @@ use openpgp_card::errors::{OcErrorStatus, OpenpgpCardError};
|
||||||
use openpgp_card::{
|
use openpgp_card::{
|
||||||
Algo, Curve, EccAttrs, EccType, KeyType, PublicKeyMaterial, RsaAttrs, Sex,
|
Algo, Curve, EccAttrs, EccType, KeyType, PublicKeyMaterial, RsaAttrs, Sex,
|
||||||
};
|
};
|
||||||
use openpgp_card_sequoia::signer::CardSigner;
|
use openpgp_card_sequoia::{make_cert, signer::CardSigner};
|
||||||
|
|
||||||
use crate::cards::TestCard;
|
use crate::cards::TestCard;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
@ -359,109 +361,7 @@ pub fn test_keygen(
|
||||||
SystemTime::from(Timestamp::from(ts)),
|
SystemTime::from(Timestamp::from(ts)),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// ---- make cert
|
let cert = make_cert(ca, key_sig, key_dec, key_aut)?;
|
||||||
|
|
||||||
let mut pp = vec![];
|
|
||||||
|
|
||||||
// 1) use the signing key as primary key
|
|
||||||
let pri = PrimaryRole::convert_key(key_sig.clone());
|
|
||||||
pp.push(Packet::from(pri));
|
|
||||||
|
|
||||||
// 2) add decryption key as subkey
|
|
||||||
let sub_dec = SubordinateRole::convert_key(key_dec);
|
|
||||||
pp.push(Packet::from(sub_dec.clone()));
|
|
||||||
|
|
||||||
// Temporary version of the cert
|
|
||||||
let cert = Cert::try_from(pp.clone())?;
|
|
||||||
|
|
||||||
// 3) make binding, sign with card -> add
|
|
||||||
{
|
|
||||||
let signing_builder =
|
|
||||||
SignatureBuilder::new(SignatureType::SubkeyBinding)
|
|
||||||
.set_signature_creation_time(SystemTime::now())?
|
|
||||||
.set_key_validity_period(std::time::Duration::new(0, 0))?
|
|
||||||
.set_key_flags(
|
|
||||||
KeyFlags::empty()
|
|
||||||
.set_storage_encryption()
|
|
||||||
.set_transport_encryption(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Allow signing on the card
|
|
||||||
let res = ca.verify_pw1_for_signing("123456")?;
|
|
||||||
res.check_ok()?;
|
|
||||||
|
|
||||||
// Card-backed signer for bindings
|
|
||||||
let mut card_signer = CardSigner::with_pubkey(ca, key_sig.clone());
|
|
||||||
|
|
||||||
let signing_bsig: Packet = sub_dec
|
|
||||||
.bind(&mut card_signer, &cert, signing_builder)?
|
|
||||||
.into();
|
|
||||||
|
|
||||||
pp.push(signing_bsig);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4) add auth subkey
|
|
||||||
let sub_aut = SubordinateRole::convert_key(key_aut);
|
|
||||||
pp.push(Packet::from(sub_aut.clone()));
|
|
||||||
|
|
||||||
// 5) make, sign binding -> add
|
|
||||||
{
|
|
||||||
let signing_builder =
|
|
||||||
SignatureBuilder::new(SignatureType::SubkeyBinding)
|
|
||||||
.set_signature_creation_time(SystemTime::now())?
|
|
||||||
.set_key_validity_period(std::time::Duration::new(0, 0))?
|
|
||||||
.set_key_flags(KeyFlags::empty().set_authentication())?;
|
|
||||||
|
|
||||||
// Allow signing on the card
|
|
||||||
let res = ca.verify_pw1_for_signing("123456")?;
|
|
||||||
res.check_ok()?;
|
|
||||||
|
|
||||||
// Card-backed signer for bindings
|
|
||||||
let mut card_signer = CardSigner::with_pubkey(ca, key_sig.clone());
|
|
||||||
|
|
||||||
let signing_bsig: Packet = sub_aut
|
|
||||||
.bind(&mut card_signer, &cert, signing_builder)?
|
|
||||||
.into();
|
|
||||||
|
|
||||||
pp.push(signing_bsig);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6) add user id from name / email
|
|
||||||
let cardholder = ca.get_cardholder_related_data()?;
|
|
||||||
|
|
||||||
// FIXME: process name field? accept email as argument?!
|
|
||||||
let uid: UserID = cardholder.name.expect("expecting name on card").into();
|
|
||||||
|
|
||||||
pp.push(uid.clone().into());
|
|
||||||
|
|
||||||
// 7) make, sign binding -> add
|
|
||||||
{
|
|
||||||
let signing_builder =
|
|
||||||
SignatureBuilder::new(SignatureType::PositiveCertification)
|
|
||||||
.set_signature_creation_time(SystemTime::now())?
|
|
||||||
.set_key_validity_period(std::time::Duration::new(0, 0))?
|
|
||||||
.set_key_flags(
|
|
||||||
// Flags for primary key
|
|
||||||
KeyFlags::empty().set_signing().set_certification(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Allow signing on the card
|
|
||||||
let res = ca.verify_pw1_for_signing("123456")?;
|
|
||||||
res.check_ok()?;
|
|
||||||
|
|
||||||
// Card-backed signer for bindings
|
|
||||||
let mut card_signer = CardSigner::with_pubkey(ca, key_sig);
|
|
||||||
|
|
||||||
let signing_bsig: Packet =
|
|
||||||
uid.bind(&mut card_signer, &cert, signing_builder)?.into();
|
|
||||||
|
|
||||||
pp.push(signing_bsig);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- process resulting Vec<Packets> as a Cert
|
|
||||||
|
|
||||||
let cert = Cert::try_from(pp)?;
|
|
||||||
|
|
||||||
let armored = String::from_utf8(cert.armored().to_vec()?)?;
|
let armored = String::from_utf8(cert.armored().to_vec()?)?;
|
||||||
|
|
||||||
let res = TestResult::Text(armored);
|
let res = TestResult::Text(armored);
|
||||||
|
|
|
@ -15,21 +15,27 @@ use openpgp::armor;
|
||||||
use openpgp::cert::amalgamation::key::ValidErasedKeyAmalgamation;
|
use openpgp::cert::amalgamation::key::ValidErasedKeyAmalgamation;
|
||||||
use openpgp::crypto::mpi;
|
use openpgp::crypto::mpi;
|
||||||
use openpgp::crypto::mpi::{ProtectedMPI, MPI};
|
use openpgp::crypto::mpi::{ProtectedMPI, MPI};
|
||||||
|
use openpgp::packet::key::KeyRole;
|
||||||
use openpgp::packet::key::{Key4, PublicParts};
|
use openpgp::packet::key::{Key4, PublicParts};
|
||||||
|
use openpgp::packet::key::{PrimaryRole, SubordinateRole};
|
||||||
use openpgp::packet::key::{SecretParts, UnspecifiedRole};
|
use openpgp::packet::key::{SecretParts, UnspecifiedRole};
|
||||||
|
use openpgp::packet::signature::SignatureBuilder;
|
||||||
|
use openpgp::packet::UserID;
|
||||||
use openpgp::packet::{key, Key};
|
use openpgp::packet::{key, Key};
|
||||||
use openpgp::parse::{stream::DecryptorBuilder, Parse};
|
use openpgp::parse::{stream::DecryptorBuilder, Parse};
|
||||||
use openpgp::policy::StandardPolicy;
|
use openpgp::policy::StandardPolicy;
|
||||||
use openpgp::serialize::stream::{Message, Signer};
|
use openpgp::serialize::stream::{Message, Signer};
|
||||||
use openpgp::types::Timestamp;
|
use openpgp::types::Timestamp;
|
||||||
|
use openpgp::types::{KeyFlags, PublicKeyAlgorithm, SignatureType};
|
||||||
|
use openpgp::{Cert, Packet};
|
||||||
use sequoia_openpgp as openpgp;
|
use sequoia_openpgp as openpgp;
|
||||||
|
|
||||||
|
use crate::signer::CardSigner;
|
||||||
use openpgp_card::card_app::CardApp;
|
use openpgp_card::card_app::CardApp;
|
||||||
use openpgp_card::{
|
use openpgp_card::{
|
||||||
errors::OpenpgpCardError, Algo, CardAdmin, CardUploadableKey, Curve,
|
errors::OpenpgpCardError, Algo, CardAdmin, CardUploadableKey, Curve,
|
||||||
EccKey, EccType, KeyType, PrivateKeyMaterial, PublicKeyMaterial, RSAKey,
|
EccKey, EccType, KeyType, PrivateKeyMaterial, PublicKeyMaterial, RSAKey,
|
||||||
};
|
};
|
||||||
use sequoia_openpgp::types::PublicKeyAlgorithm;
|
|
||||||
|
|
||||||
mod decryptor;
|
mod decryptor;
|
||||||
pub mod signer;
|
pub mod signer;
|
||||||
|
@ -160,6 +166,118 @@ pub fn public_key_material_to_key(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a Cert from the three subkeys on a card.
|
||||||
|
/// (Calling this multiple times will result in different Certs!)
|
||||||
|
///
|
||||||
|
/// FIXME: make dec/auth keys optional
|
||||||
|
///
|
||||||
|
/// FIXME: accept optional metadata for user_id(s)?
|
||||||
|
pub fn make_cert(
|
||||||
|
ca: &mut CardApp,
|
||||||
|
key_sig: Key<PublicParts, UnspecifiedRole>,
|
||||||
|
key_dec: Key<PublicParts, UnspecifiedRole>,
|
||||||
|
key_aut: Key<PublicParts, UnspecifiedRole>,
|
||||||
|
) -> Result<Cert> {
|
||||||
|
let mut pp = vec![];
|
||||||
|
|
||||||
|
// 1) use the signing key as primary key
|
||||||
|
let pri = PrimaryRole::convert_key(key_sig.clone());
|
||||||
|
pp.push(Packet::from(pri));
|
||||||
|
|
||||||
|
// 2) add decryption key as subkey
|
||||||
|
let sub_dec = SubordinateRole::convert_key(key_dec);
|
||||||
|
pp.push(Packet::from(sub_dec.clone()));
|
||||||
|
|
||||||
|
// Temporary version of the cert
|
||||||
|
let cert = Cert::try_from(pp.clone())?;
|
||||||
|
|
||||||
|
// 3) make binding, sign with card -> add
|
||||||
|
{
|
||||||
|
let signing_builder =
|
||||||
|
SignatureBuilder::new(SignatureType::SubkeyBinding)
|
||||||
|
.set_signature_creation_time(SystemTime::now())?
|
||||||
|
.set_key_validity_period(std::time::Duration::new(0, 0))?
|
||||||
|
.set_key_flags(
|
||||||
|
KeyFlags::empty()
|
||||||
|
.set_storage_encryption()
|
||||||
|
.set_transport_encryption(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Allow signing on the card
|
||||||
|
let res = ca.verify_pw1_for_signing("123456")?;
|
||||||
|
res.check_ok()?;
|
||||||
|
|
||||||
|
// Card-backed signer for bindings
|
||||||
|
let mut card_signer = CardSigner::with_pubkey(ca, key_sig.clone());
|
||||||
|
|
||||||
|
let signing_bsig: Packet = sub_dec
|
||||||
|
.bind(&mut card_signer, &cert, signing_builder)?
|
||||||
|
.into();
|
||||||
|
|
||||||
|
pp.push(signing_bsig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) add auth subkey
|
||||||
|
let sub_aut = SubordinateRole::convert_key(key_aut);
|
||||||
|
pp.push(Packet::from(sub_aut.clone()));
|
||||||
|
|
||||||
|
// 5) make, sign binding -> add
|
||||||
|
{
|
||||||
|
let signing_builder =
|
||||||
|
SignatureBuilder::new(SignatureType::SubkeyBinding)
|
||||||
|
.set_signature_creation_time(SystemTime::now())?
|
||||||
|
.set_key_validity_period(std::time::Duration::new(0, 0))?
|
||||||
|
.set_key_flags(KeyFlags::empty().set_authentication())?;
|
||||||
|
|
||||||
|
// Allow signing on the card
|
||||||
|
let res = ca.verify_pw1_for_signing("123456")?;
|
||||||
|
res.check_ok()?;
|
||||||
|
|
||||||
|
// Card-backed signer for bindings
|
||||||
|
let mut card_signer = CardSigner::with_pubkey(ca, key_sig.clone());
|
||||||
|
|
||||||
|
let signing_bsig: Packet = sub_aut
|
||||||
|
.bind(&mut card_signer, &cert, signing_builder)?
|
||||||
|
.into();
|
||||||
|
|
||||||
|
pp.push(signing_bsig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6) add user id from name / email
|
||||||
|
let cardholder = ca.get_cardholder_related_data()?;
|
||||||
|
|
||||||
|
// FIXME: process name field? accept email as argument?!
|
||||||
|
let uid: UserID = cardholder.name.expect("expecting name on card").into();
|
||||||
|
|
||||||
|
pp.push(uid.clone().into());
|
||||||
|
|
||||||
|
// 7) make, sign binding -> add
|
||||||
|
{
|
||||||
|
let signing_builder =
|
||||||
|
SignatureBuilder::new(SignatureType::PositiveCertification)
|
||||||
|
.set_signature_creation_time(SystemTime::now())?
|
||||||
|
.set_key_validity_period(std::time::Duration::new(0, 0))?
|
||||||
|
.set_key_flags(
|
||||||
|
// Flags for primary key
|
||||||
|
KeyFlags::empty().set_signing().set_certification(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Allow signing on the card
|
||||||
|
let res = ca.verify_pw1_for_signing("123456")?;
|
||||||
|
res.check_ok()?;
|
||||||
|
|
||||||
|
// Card-backed signer for bindings
|
||||||
|
let mut card_signer = CardSigner::with_pubkey(ca, key_sig);
|
||||||
|
|
||||||
|
let signing_bsig: Packet =
|
||||||
|
uid.bind(&mut card_signer, &cert, signing_builder)?.into();
|
||||||
|
|
||||||
|
pp.push(signing_bsig);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cert::try_from(pp)
|
||||||
|
}
|
||||||
|
|
||||||
/// Implement the `CardUploadableKey` trait that openpgp-card uses to
|
/// Implement the `CardUploadableKey` trait that openpgp-card uses to
|
||||||
/// upload (sub)keys to a card.
|
/// upload (sub)keys to a card.
|
||||||
impl CardUploadableKey for SequoiaKey {
|
impl CardUploadableKey for SequoiaKey {
|
||||||
|
@ -326,7 +444,7 @@ impl EccKey for SqEccKey {
|
||||||
/// more intent.
|
/// more intent.
|
||||||
pub fn upload_from_cert_yolo(
|
pub fn upload_from_cert_yolo(
|
||||||
oca: &mut CardAdmin,
|
oca: &mut CardAdmin,
|
||||||
cert: &sequoia_openpgp::Cert,
|
cert: &openpgp::Cert,
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
@ -370,7 +488,7 @@ pub fn upload_key(
|
||||||
|
|
||||||
pub fn decrypt(
|
pub fn decrypt(
|
||||||
ca: &mut CardApp,
|
ca: &mut CardApp,
|
||||||
cert: &sequoia_openpgp::Cert,
|
cert: &openpgp::Cert,
|
||||||
msg: Vec<u8>,
|
msg: Vec<u8>,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
let mut decrypted = Vec::new();
|
let mut decrypted = Vec::new();
|
||||||
|
@ -392,7 +510,7 @@ pub fn decrypt(
|
||||||
|
|
||||||
pub fn sign(
|
pub fn sign(
|
||||||
ca: &mut CardApp,
|
ca: &mut CardApp,
|
||||||
cert: &sequoia_openpgp::Cert,
|
cert: &openpgp::Cert,
|
||||||
input: &mut dyn io::Read,
|
input: &mut dyn io::Read,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let mut armorer = armor::Writer::new(vec![], armor::Kind::Signature)?;
|
let mut armorer = armor::Writer::new(vec![], armor::Kind::Signature)?;
|
||||||
|
|
Loading…
Reference in a new issue