rust: Refactoring and reduce API surface

Prepare pv & pv_core crates to be released on crates.io:
* Remove any unused API to stay flexible
* Remove utils dependency
* Move cli, tmpfile and version utilities to local utils crate
* Use the new utilities in the pv tools
* Rename Secret into Confidential to avoid confusion of Secret (now
  Confidential) and AddSecret requests.
* Move the uvsecret module out of the request module and change the name
  to secret.
* Cleanup dependencies
* Precise and correct minimal dependency versions
* Inline `Aes256Key::from_digest`

The cleanup ensures that the code also compiles with the dependencies
resolved to their minimal versions using:

$ cargo +nightly -Z minimal-versions update
$ cargo build

For more information refer to this blog post:
https://users.rust-lang.org/t/psa-please-specify-precise-dependency-versions-in-cargo-toml/71277/8

Signed-off-by: Marc Hartmayer <mhartmay@de.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
Steffen Eiden
2024-05-21 16:26:51 +02:00
parent 5648b924d6
commit 381fecfc44
44 changed files with 499 additions and 490 deletions
+1 -1
View File
@@ -5,8 +5,8 @@
use crate::cli::AddSecretOpt;
use anyhow::{Context, Result};
use log::warn;
use pv::misc::get_reader_from_cli_file_arg;
use pv::uv::{AddCmd, UvDevice};
use utils::get_reader_from_cli_file_arg;
/// Do an Add Secret UVC
pub fn add(opt: &AddSecretOpt) -> Result<()> {
+35 -41
View File
@@ -1,23 +1,24 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp. 2023
// Copyright IBM Corp. 2023, 2024
use crate::cli::{AddSecretType, CreateSecretFlags, CreateSecretOpt};
use anyhow::{anyhow, bail, Context, Result};
use anyhow::{anyhow, bail, Context, Error, Result};
use log::{debug, info, trace, warn};
use pv::{
misc::{
get_writer_from_cli_file_arg, open_file, parse_hex, pv_guest_bit_set, read_certs,
read_exact_file, read_file, read_private_key, try_parse_u128, try_parse_u64, write,
open_file, parse_hex, pv_guest_bit_set, read_exact_file, read_file, try_parse_u128,
try_parse_u64, write,
},
request::{
openssl::pkey::{PKey, Public},
uvsecret::{AddSecretFlags, AddSecretRequest, AddSecretVersion, ExtSecret, GuestSecret},
BootHdrTags, HkdVerifier, ReqEncrCtx, Request, SymKeyType,
openssl::pkey::{PKey, Private},
BootHdrTags, ReqEncrCtx, Request, SymKeyType,
},
secret::{AddSecretFlags, AddSecretRequest, AddSecretVersion, ExtSecret, GuestSecret},
uv::ConfigUid,
};
use serde_yaml::Value;
use utils::get_writer_from_cli_file_arg;
fn write_out<D: AsRef<[u8]>>(path: &str, data: D, ctx: &str) -> pv::Result<()> {
let mut wr = get_writer_from_cli_file_arg(path)?;
@@ -40,8 +41,8 @@ pub fn create(opt: &CreateSecretOpt) -> Result<()> {
debug!("Generated Add-secret request");
// Add host-key documents
let verifier = opt.certificate_args.verifier()?;
read_and_verify_hkds(&opt.certificate_args.host_key_documents, verifier)?
opt.certificate_args
.get_verified_hkds("secret")?
.into_iter()
.for_each(|k| asrcb.add_hostkey(k));
@@ -57,6 +58,13 @@ pub fn create(opt: &CreateSecretOpt) -> Result<()> {
write_secret(&opt.secret, &asrcb)
}
/// Read+parse the first key from the buffer.
fn read_private_key(buf: &[u8]) -> Result<PKey<Private>> {
PKey::private_key_from_der(buf)
.or_else(|_| PKey::private_key_from_pem(buf))
.map_err(Error::new)
}
/// Set-up the `add-secret request` from command-line arguments
fn build_asrcb(opt: &CreateSecretOpt) -> Result<AddSecretRequest> {
debug!("Build add-secret request");
@@ -191,38 +199,6 @@ fn read_cuid(asrcb: &mut AddSecretRequest, opt: &CreateSecretOpt) -> Result<()>
Ok(())
}
/// reads HKDs into memory, verifies them with the provided HKD verifier.
/// returns list of public keys or Err
/// Aborts on first error
fn read_and_verify_hkds(
hkds: &Vec<String>,
verifier: Box<dyn HkdVerifier>,
) -> Result<Vec<PKey<Public>>> {
let mut res = Vec::with_capacity(hkds.len());
for hkd in hkds {
let hk = read_file(hkd, "host-key document")?;
let certs = read_certs(&hk).with_context(|| {
format!("The provided Host Key Document in '{hkd}' is not in PEM or DER format")
})?;
if certs.is_empty() {
let msg = format!(
"The provided host key document in {} contains no certificate!",
hkd
);
return Err(anyhow!(msg));
}
if certs.len() > 1 {
warn!("The host key document in '{hkd}' contains more than one certificate! Only the first certificate will be used.")
}
// len is >= 1 -> unwrap will succeed
let c = certs.first().unwrap();
verifier.verify(c)?;
res.push(c.public_key()?);
info!("Use host-key document at '{hkd}'");
}
Ok(res)
}
/// Write the generated secret (if any) to the specified output stream
fn write_secret(secret: &AddSecretType, asrcb: &AddSecretRequest) -> Result<()> {
if let AddSecretType::Association {
@@ -262,3 +238,21 @@ fn write_secret(secret: &AddSecretType, asrcb: &AddSecretRequest) -> Result<()>
};
Ok(())
}
#[cfg(test)]
mod test {
#[test]
fn read_private_key() {
let key = include_bytes!("../../../pv/tests/assets/keys/rsa3072key.pem");
let key = super::read_private_key(key).unwrap();
assert_eq!(key.rsa().unwrap().size(), 384);
}
#[test]
fn read_private_key_fail() {
let key = include_bytes!("create.rs");
let key = super::read_private_key(key);
assert!(key.is_err());
}
}
+2 -4
View File
@@ -5,10 +5,8 @@
use crate::cli::{ListSecretOpt, ListSecretOutputType};
use anyhow::{Context, Result};
use log::warn;
use pv::{
misc::{get_writer_from_cli_file_arg, STDOUT},
uv::{ListCmd, SecretList, UvDevice, UvcSuccess},
};
use pv::uv::{ListCmd, SecretList, UvDevice, UvcSuccess};
use utils::{get_writer_from_cli_file_arg, STDOUT};
/// Do a List Secrets UVC
pub fn list(opt: &ListSecretOpt) -> Result<()> {
+5 -7
View File
@@ -1,14 +1,12 @@
use crate::cli::VerifyOpt;
use anyhow::{anyhow, Context, Result};
use log::warn;
use pv::misc::{read_certs, read_file};
use pv::{
misc::{get_reader_from_cli_file_arg, get_writer_from_cli_file_arg, read_certs, read_file},
request::{
openssl::pkey::{PKey, Public},
uvsecret::verify_asrcb_and_get_user_data,
},
request::openssl::pkey::{PKey, Public},
secret::verify_asrcb_and_get_user_data,
};
use crate::cli::VerifyOpt;
use utils::{get_reader_from_cli_file_arg, get_writer_from_cli_file_arg};
/// read the content of a DER or PEM x509 and return the public key
fn read_sgn_key(path: &str) -> Result<PKey<Public>> {