rust/pv: Use a SecretId struct instead of an array

This streamlines and unifies the use and (de)serialization of structs
using a secret id. As a bonus, the hidden `for_pv` module is not longer
needed.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Julian Ruess <julianr@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Steffen Eiden
2024-02-15 17:06:04 +01:00
committed by Jan Höppner
parent 81a1e13f3b
commit c53dfa9754
6 changed files with 161 additions and 76 deletions
+1 -5
View File
@@ -35,11 +35,7 @@ const PAGESIZE: usize = 0x1000;
/// Definitions and functions for interacting with the Ultravisor
pub mod uv {
pub use pv_core::uv::{
uv_ioctl, ConfigUid, UvCmd, UvDevice, UvDeviceInfo, UvFlags, UvcSuccess,
};
pub use pv_core::uv::{AddCmd, ListCmd, LockCmd};
pub use pv_core::uv::{ListableSecretType, SecretEntry, SecretList};
pub use pv_core::uv::*;
}
/// Miscellaneous functions and definitions
+5 -5
View File
@@ -23,7 +23,7 @@ use pv_core::request::RequestVersion;
use zerocopy::AsBytes;
/// Internal wrapper for Guest Secret, so that we can dump it in the form the UV wants it to be
#[derive(Debug, Clone)]
#[derive(Debug)]
struct BinGuestSecret(GuestSecret);
impl BinGuestSecret {
/// Reference to the confidential data
@@ -40,7 +40,7 @@ impl BinGuestSecret {
let mut buf = vec![0; 48];
buf[3] = 2;
buf[7] = 0x20;
buf[16..48].copy_from_slice(id.as_slice());
buf[16..48].copy_from_slice(id.as_ref());
buf
}
}
@@ -75,7 +75,7 @@ impl ReqAuthData {
}
}
#[derive(Debug, Clone)]
#[derive(Debug)]
struct ReqConfData {
secret: BinGuestSecret,
extension_secret: Secret<[u8; 32]>,
@@ -164,7 +164,7 @@ impl From<AddSecretVersion> for RequestVersion {
/// | AES GCM Tag (16) |
/// |_____________________________________________________________|
///```
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct AddSecretRequest {
version: AddSecretVersion,
aad: ReqAuthData,
@@ -348,7 +348,7 @@ mod test {
fn guest_secret_bin_ap() {
let gs: BinGuestSecret = GuestSecret::Association {
name: "test".to_string(),
id: [1; 32],
id: [1; 32].into(),
secret: [2; 32].into(),
}
.into();
+12 -37
View File
@@ -8,13 +8,14 @@ use crate::{
request::{hash, openssl::MessageDigest, random_array, Secret},
Result,
};
use pv_core::for_pv::{ser_gsid, SECRET_ID_SIZE};
use pv_core::uv::SecretId;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
const SECRET_SIZE: usize = 32;
/// A Secret to be added in [`AddSecretRequest`]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum GuestSecret {
/// No guest secret
Null,
@@ -24,10 +25,9 @@ pub enum GuestSecret {
Association {
/// Name of the secret
name: String,
#[serde(serialize_with = "ser_gsid", deserialize_with = "de_gsid")]
/// SHA256 hash of [`GuestSecret::Association::name`]
id: [u8; SECRET_ID_SIZE],
/// Confidential actual assocuiation secret (32 bytes)
id: SecretId,
/// Confidential actual association secret (32 bytes)
#[serde(skip)]
secret: Secret<[u8; SECRET_SIZE]>,
},
@@ -46,7 +46,10 @@ impl GuestSecret {
where
O: Into<Option<[u8; SECRET_SIZE]>>,
{
let id = hash(MessageDigest::sha256(), name.as_bytes())?.to_vec();
let id: [u8; SecretId::ID_SIZE] = hash(MessageDigest::sha256(), name.as_bytes())?
.to_vec()
.try_into()
.unwrap();
let secret = match secret.into() {
Some(s) => s,
None => random_array()?,
@@ -54,39 +57,11 @@ impl GuestSecret {
Ok(GuestSecret::Association {
name: name.to_string(),
id: id.try_into().unwrap(),
id: id.into(),
secret: secret.into(),
})
}
}
fn de_gsid<'de, D>(de: D) -> Result<[u8; 32], D::Error>
where
D: serde::Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> serde::de::Visitor<'de> for FieldVisitor {
type Value = [u8; SECRET_ID_SIZE];
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a `32 bytes long hexstring` prepended with 0x")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if s.len() != SECRET_ID_SIZE * 2 + 2 {
return Err(serde::de::Error::invalid_length(s.len(), &self));
}
let nb = s.strip_prefix("0x").ok_or_else(|| {
serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &self)
})?;
crate::misc::parse_hex(nb)
.try_into()
.map_err(|_| serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &self))
}
}
de.deserialize_identifier(FieldVisitor)
}
#[cfg(test)]
mod test {
@@ -106,7 +81,7 @@ mod test {
let secret = GuestSecret::association("association secret", secret_value).unwrap();
let exp = GuestSecret::Association {
name,
id: exp_id,
id: exp_id.into(),
secret: secret_value.into(),
};
assert_eq!(secret, exp);
@@ -121,7 +96,7 @@ mod test {
];
let asc = GuestSecret::Association {
name: "test123".to_string(),
id,
id: id.into(),
secret: [0; 32].into(),
};