-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable KVM_MEM_ENCRYPT_OP
ioctl for AMD SEV
#111
Conversation
The `KVM_MEM_ENCRYPT_OP` ioctl is used to access AMD SEV (Secure Encrypted Virtualization) feature. When enabled, memory contents of a VM will be transparently encrypted with a key unique to that VM. This patch added implementation, documentation and related tests for the following SEV commands: - KVM_SEV_INIT - KVM_SEV_LAUNCH_START - KVM_SEV_LAUNCH_UPDATE_DATA - KVM_SEV_LAUNCH_MEASURE - KVM_SEV_LAUNCH_FINISH - KVM_SEV_LAUNCH_SECRET Note: this work is based on enarx/ketuvim. See [1]_ for details. [1] rust-vmm/community#62 Signed-off-by: Kailun Qin <[email protected]>
This introduces too much dependency crates:( |
Hi @jiangliu , Thanks for the comments. Most of the dependency crates introduced are dev-only and the rest for runtime are feature-controlled. For the test-only dependencies, a large part of them aim to facilitate users with the construction of SEV cert chain (from remote). We can get rid of them if we assume that users have already had their own available locally. This depends on how we trade-off and I'd like to see more feedbacks. Actually, the only one runtime dependency needed is the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apart from some code quirks (left comments), my main concern is how to consume the sev
crate dependency (currently a crate in enarx
) 🤔
@@ -12,6 +12,19 @@ license = "Apache-2.0 OR MIT" | |||
libc = ">=0.2.39" | |||
kvm-bindings = { version = ">=0.2.0", features = ["fam-wrappers"] } | |||
vmm-sys-util = ">=0.2.1" | |||
bitflags = { version = ">=1.2.1", optional = true } | |||
sev = { path = "./sev", features = ["openssl"], optional = true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no sev
crate, does this refer to the sev
mod?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or did you have the sev
crate locally in your workspace? The PR doesn't build without it.
LE: I think this is the sev
crate from the enarx repo; but, as enarx
doesn't have a Cargo.toml
(they seem to use a different build system, cargo make
?), Cargo can't get the crate dependency right with
sev = { git = "https://github.com/enarx/enarx.git", features = ["openssl"], optional = true }
This would be a blocker in publishing a new version of kvm-ioctls
with sev
support: the sev
crate needs to be published first.
In the meantime, for playing around, maybe you could get away with a multiple-dependency like explained here. Cargo would look for the sev
crate on crates.io and, until it finds it there, pick it up from the local repo (to get the CI to pass, you'd have to yank it into your fork and add it to the PR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's more, maybe you should also restrict the sev
dependencies to target=x86_64
as they won't build on ARM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or did you have thesev
crate locally in your workspace? The PR doesn't build without it.
LE: I think this is thesev
crate from the enarx repo; but, asenarx
doesn't have aCargo.toml
(they seem to use a different build system,cargo make
?), Cargo can't get the crate dependency right withsev = { git = "https://github.com/enarx/enarx.git", features = ["openssl"], optional = true }This would be a blocker in publishing a new version of
kvm-ioctls
withsev
support: thesev
crate needs to be published first.
In the meantime, for playing around, maybe you could get away with a multiple-dependency like explained here. Cargo would look for thesev
crate on crates.io and, until it finds it there, pick it up from the local repo (to get the CI to pass, you'd have to yank it into your fork and add it to the PR).
Yes, I do have a modified sev
crate in my workspace, which also implements the traits to resolve compilation issues you mentioned below. (that is why I marked this PR as a draft version ;))
As enarx team has cited in another thread. Let's wait a moment for their coming release of sev
crate and APIs. I'll have an update based on that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's more, maybe you should also restrict the
sev
dependencies totarget=x86_64
as they won't build on ARM.
Yes agree, will update.
lazy_static = "1.4.0" | ||
|
||
[features] | ||
default = ["amd-sev"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should be a default feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, will remove the default.
/// Learn from ``SevState`` introduced in QEMU, adding few changes. | ||
/// An enumeration of SEV state information used during @query-sev. | ||
/// | ||
/// @Uninit: The guest is uninitialized. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: these should be converted to doc comments.
pub fn start(self, start: Start) -> Result<SevLaunch<LaunchUpdate>> { | ||
let start = kvm_sev_launch_start { | ||
handle: 0, | ||
policy: start.policy.into(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't compile on my machine because there's no Into<u32>
for Policy
.
/// The guest owner may wait to provide the guest with confidential information until | ||
/// it can verify the measurement thru comparison. | ||
pub fn measure(self) -> Result<SevLaunch<LaunchSecret>> { | ||
let mut mr = Measurement::default(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't compile on my machine because there's no impl Default
for Measurement
.
|
||
impl SevLaunch<LaunchSecret> { | ||
/// Get the measurement kept by the SEV launch context (in a `LaunchSecret` state) | ||
pub fn get_measure(&self) -> Measurement { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: getters usually lack the get_
prefix in Rust
self.sev_ioctl(SevCmd::LaunchSecret, secret)?; | ||
Ok(()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.sev_ioctl(SevCmd::LaunchSecret, secret)?; | |
Ok(()) | |
self.sev_ioctl(SevCmd::LaunchSecret, secret) |
/// | ||
/// @ReceiveUpdate: The guest is currently being migrated from another machine. | ||
#[derive(PartialEq, Debug)] | ||
pub struct Uninit; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is meant to be an enumeration, so why not express it as an Enum
? Also, modelling the state transitions with the From
trait is a bit weird to me, and not very idiomatic IMO - From
conceptually implies equivalence between the 2 operands, while a state machine implies not just non-equivalence, but order between the states. I believe an Enum
here and explicit transition functions between the states would make the code clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is meant to be an enumeration, so why not express it as an
Enum
? Also, modelling the state transitions with theFrom
trait is a bit weird to me, and not very idiomatic IMO -From
conceptually implies equivalence between the 2 operands, while a state machine implies not just non-equivalence, but order between the states. I believe anEnum
here and explicit transition functions between the states would make the code clearer.
Thanks for the suggestions. Seems reasonable to me. I'll make an update in the next version.
pub fn create_sev_launch(self) -> Result<SevLaunch<Init>> { | ||
let launch = SevLaunch::new_with_vm(self)?; | ||
|
||
Ok(launch.init()?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok(launch.init()?) | |
launch.init() |
/* Memory Encryption Commands */ | ||
/* KVM_MEMORY_ENCRYPT_OP */ | ||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] | ||
ioctl_iowr_nr!(KVM_MEMORY_ENCRYPT_OP, KVMIO, 0xba, c_ulong); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be gated to feature = "amd-sev"
too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this should be gated to feature = "amd-sev"
.
Hi, @kailun-qin! Are you still interested in merging this PR? |
Hi @lauralt , |
This support was merged in #178. Closing this. |
The
KVM_MEM_ENCRYPT_OP
ioctl is used to access AMD SEV (SecureEncrypted Virtualization) feature. When enabled, memory contents of a VM
will be transparently encrypted with a key unique to that VM.
This patch added implementation, documentation and related tests for the
following SEV commands:
Note: this work is based on enarx/ketuvim. See [1]_ for details.
[1] rust-vmm/community#62
Signed-off-by: Kailun Qin [email protected]