Simplify gen_subkeys() now that AlgoSimple has simple, unambiguous values for RSA.

This commit is contained in:
Heiko Schaefer 2021-12-02 13:19:34 +01:00
parent c37c34e525
commit b127046bd3
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D

View file

@ -455,28 +455,25 @@ fn generate_keys(
// Because of this, for generation of RSA keys, here we take the approach // Because of this, for generation of RSA keys, here we take the approach
// of first trying one variant, and then if that fails, try the other. // of first trying one variant, and then if that fails, try the other.
let algos = match algo.as_deref() { let a = match algo.as_deref() {
None => vec![], None => None,
Some("rsa2048") => vec![AlgoSimple::RSA2k(32), AlgoSimple::RSA2k(17)], Some("rsa2048") => Some(AlgoSimple::RSA2k),
Some("rsa3072") => vec![AlgoSimple::RSA3k(32), AlgoSimple::RSA3k(17)], Some("rsa3072") => Some(AlgoSimple::RSA3k),
Some("rsa4096") => vec![AlgoSimple::RSA4k(32), AlgoSimple::RSA4k(17)], Some("rsa4096") => Some(AlgoSimple::RSA4k),
Some("nistp256") => vec![AlgoSimple::NIST256], Some("nistp256") => Some(AlgoSimple::NIST256),
Some("nistp384") => vec![AlgoSimple::NIST384], Some("nistp384") => Some(AlgoSimple::NIST384),
Some("nistp521") => vec![AlgoSimple::NIST521], Some("nistp521") => Some(AlgoSimple::NIST521),
Some("25519") => vec![AlgoSimple::Curve25519], Some("25519") => Some(AlgoSimple::Curve25519),
_ => return Err(anyhow!("Unexpected algorithm")), _ => return Err(anyhow!("Unexpected algorithm")),
}; };
log::info!( log::info!(" Key generation will be attempted with algo: {:?}", a);
" Key generation will be attempted with these algos: {:?}",
algos
);
// 2) Then, generate keys on the card. // 2) Then, generate keys on the card.
// We need "admin" access to the card for this). // We need "admin" access to the card for this).
let (key_sig, key_dec, key_aut) = { let (key_sig, key_dec, key_aut) = {
if let Ok(mut admin) = util::verify_to_admin(&mut open, pw3_path) { if let Ok(mut admin) = util::verify_to_admin(&mut open, pw3_path) {
gen_subkeys(&mut admin, decrypt, auth, algos)? gen_subkeys(&mut admin, decrypt, auth, a)?
} else { } else {
return Err(anyhow!("Failed to open card in admin mode.")); return Err(anyhow!("Failed to open card in admin mode."));
} }
@ -518,91 +515,19 @@ fn gen_subkeys(
admin: &mut Admin, admin: &mut Admin,
decrypt: bool, decrypt: bool,
auth: bool, auth: bool,
algos: Vec<AlgoSimple>, algo: Option<AlgoSimple>,
) -> Result<(PublicKey, Option<PublicKey>, Option<PublicKey>)> { ) -> Result<(PublicKey, Option<PublicKey>, Option<PublicKey>)> {
// We begin with the signing subkey, which is mandatory. // We begin by generating the signing subkey, which is mandatory.
// If there are multiple algorithms we should try (i.e. two rsa
// variants), we'll attempt to make the signing subkey with each of
// them, and continue with the first one that works, if any.
println!(" Generate subkey for Signing"); println!(" Generate subkey for Signing");
let (alg, key_sig) = if algos.is_empty() { let (pkm, ts) = admin.generate_key_simple(KeyType::Signing, algo)?;
// Handle unset algorithm from user (-> leave algo as is on the card) let key_sig = public_key_material_to_key(&pkm, KeyType::Decryption, ts)?;
log::info!(" Running key generation with implicit algo");
let (pkm, ts) = admin.generate_key_simple(KeyType::Signing, None)?;
let key = public_key_material_to_key(&pkm, KeyType::Signing, ts)?;
(None, key)
} else {
// Try list of algos until one works - or return list of all errors.
let mut errors = vec![];
let mut algo: Option<AlgoSimple> = None;
let mut key_sig: Option<PublicKey> = None;
// Check each algo while making key_sig.
//
// Return the result for the first one that works, and keep using
// that algo.
//
// If none of them work, fail and return all errors
for (n, alg) in algos.iter().enumerate() {
let a = Some(*alg);
log::info!(" Trying key generation with algo {:?}", alg);
match admin.generate_key_simple(KeyType::Signing, a) {
Ok((pkm, ts)) => {
// generated a valid key -> return it
let key = public_key_material_to_key(
&pkm,
KeyType::Signing,
ts,
)?;
algo = a;
key_sig = Some(key);
break;
}
Err(e) => match (n, n == algos.len() - 1) {
// there was only one algo, and it failed
(0, true) => return Err(e.into()),
// there was an error, but there are more algo to try
(_, false) => errors.push(e),
// there were multiple algo, there was an error, and
// this is the last algo
(_, true) => {
errors.push(e);
let err = anyhow::anyhow!(
"Key generation failed for all algorithm \
variants {:x?} ({:?})",
errors,
algos
);
return Err(err);
}
},
};
}
// Neither of these should be possible, but the compiler can't tell.
assert!(algo.is_some());
assert!(key_sig.is_some());
(algo, key_sig.unwrap())
};
// make decryption subkey (unless disabled), with the same algorithm as // make decryption subkey (unless disabled), with the same algorithm as
// the sig key // the sig key
let key_dec = if decrypt { let key_dec = if decrypt {
println!(" Generate subkey for Decryption"); println!(" Generate subkey for Decryption");
let (pkm, ts) = admin.generate_key_simple(KeyType::Decryption, alg)?; let (pkm, ts) =
admin.generate_key_simple(KeyType::Decryption, algo)?;
Some(public_key_material_to_key(&pkm, KeyType::Decryption, ts)?) Some(public_key_material_to_key(&pkm, KeyType::Decryption, ts)?)
} else { } else {
None None
@ -610,11 +535,10 @@ fn gen_subkeys(
// make authentication subkey (unless disabled), with the same // make authentication subkey (unless disabled), with the same
// algorithm as the sig key // algorithm as the sig key
let key_aut = if auth { let key_aut = if auth {
println!(" Generate subkey for Authentication"); println!(" Generate subkey for Authentication");
let (pkm, ts) = let (pkm, ts) =
admin.generate_key_simple(KeyType::Authentication, alg)?; admin.generate_key_simple(KeyType::Authentication, algo)?;
Some(public_key_material_to_key( Some(public_key_material_to_key(
&pkm, &pkm,