Skip to content

Commit

Permalink
rand: Removing use of openssl rand for crypto
Browse files Browse the repository at this point in the history
According to the documentation, openssl's `rand_bytes(...)` function will be
seeded with `/dev/urandom`, which is not sound for cryptographic
application. We will be switching to using the `rdrand` crate which will
utilize the X86_64 microcode call to `RDRAND`, instead. All X86_64
instructions are protected by the Guest Hypervisor Communication Block
(GHCB), and may thus be presumed secure for cryptographic practices in
the context of confidential compute.

Signed-off-by: Larry Dewey <larry.dewey@amd.com>
  • Loading branch information
larrydewey committed Aug 2, 2024
1 parent a3c91d7 commit 4362d05
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 12 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ doc = false

[features]
default = ["sev", "snp"]
openssl = ["dep:openssl", "rdrand"]
hw_tests = []
dangerous_hw_tests = ["hw_tests"]
sev = []
Expand Down Expand Up @@ -68,6 +69,7 @@ sha2 = { version = "0.10.8", optional = true }
x509-cert = { version = "0.2.5", optional = true }
byteorder = "1.4.3"
base64 = "0.22.1"
rdrand = { version = "^0.8", optional = true }

[target.'cfg(target_os = "linux")'.dev-dependencies]
kvm-ioctls = ">=0.16"
Expand Down
46 changes: 46 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: Apache-2.0

use bincode;
#[cfg(feature = "openssl")]
use openssl::error::ErrorStack;
use std::{
array::TryFromSliceError,
convert::From,
Expand All @@ -9,6 +11,9 @@ use std::{
io,
};

#[cfg(feature = "openssl")]
use rdrand::ErrorCode;

use std::os::raw::c_int;

#[cfg(feature = "openssl")]
Expand Down Expand Up @@ -159,6 +164,13 @@ pub enum Indeterminate<T: Debug> {
Unknown,
}

impl<T: Debug> From<T> for Indeterminate<T> {
/// Creates an easy
fn from(value: T) -> Self {
Self::Known(value)
}
}

#[derive(Debug)]
/// Wrapper Error for Firmware or User API Errors
pub enum UserApiError {
Expand Down Expand Up @@ -1048,3 +1060,37 @@ impl std::convert::From<LargeArrayError> for MeasurementError {
Self::LargeArrayError(value)
}
}

#[cfg(feature = "openssl")]
/// Used to describe errors related to SEV-ES "Sessions".
pub enum SessionError {
/// Errors which occur from using the rdrand crate.
RandError(ErrorCode),

/// OpenSSL Error Stack
OpenSSLStack(ErrorStack),

/// Errors occuring from IO operations.
IOError(std::io::Error),
}

#[cfg(feature = "openssl")]
impl From<ErrorCode> for SessionError {
fn from(value: ErrorCode) -> Self {
Self::RandError(value)
}
}

#[cfg(feature = "openssl")]
impl From<std::io::Error> for SessionError {
fn from(value: std::io::Error) -> Self {
Self::IOError(value)
}
}

#[cfg(feature = "openssl")]
impl From<ErrorStack> for SessionError {
fn from(value: ErrorStack) -> Self {
Self::OpenSSLStack(value)
}
}
18 changes: 16 additions & 2 deletions src/session/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use std::{
ptr::write_volatile,
};

use rdrand::{ErrorCode, RdRand};

use openssl::*;

#[repr(transparent)]
Expand Down Expand Up @@ -55,9 +57,21 @@ impl Key {
Key(vec![0u8; size])
}

pub fn random(size: usize) -> Result<Self> {
/// Will attempt to create a random Key derived from the CPU RDRAND instruction.
pub fn random(size: usize) -> std::result::Result<Self, ErrorCode> {
// Create a new empty key to store the pseudo-random bytes in.
let mut key = Key::zeroed(size);
rand::rand_bytes(&mut key)?;

// Instantiate a pseudo-random number generator instance to pull
// random data from the CPU RDRAND instruction set.
let mut rng = RdRand::new()?;

// Attempt to generate N-number of bytes specified by the `size`
// parameter, storing the bytes inside they key generated at the
// start of the method.
rng.try_fill_bytes(&mut key)?;

// Return the key when successful.
Ok(key)
}
}
Expand Down
39 changes: 29 additions & 10 deletions src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
mod key;

use crate::error::SessionError;

use super::*;

use std::io::{Error, ErrorKind, Result};

use rdrand::{ErrorCode, RdRand};

use openssl::*;

/// Represents a brand-new secure channel with the AMD SP.
Expand Down Expand Up @@ -43,9 +47,9 @@ impl launch::sev::Policy {
}

impl std::convert::TryFrom<launch::sev::Policy> for Session<Initialized> {
type Error = std::io::Error;
type Error = ErrorCode;

fn try_from(value: launch::sev::Policy) -> Result<Self> {
fn try_from(value: launch::sev::Policy) -> std::result::Result<Self, Self::Error> {
Ok(Self {
tek: key::Key::random(16)?,
tik: key::Key::random(16)?,
Expand Down Expand Up @@ -88,7 +92,10 @@ impl Session<Initialized> {
}

/// Produces data needed to initiate the SEV launch sequence.
pub fn start(&self, chain: certs::sev::Chain) -> Result<launch::sev::Start> {
pub fn start(
&self,
chain: certs::sev::Chain,
) -> std::result::Result<launch::sev::Start, SessionError> {
use certs::sev::*;

let pdh = chain.verify()?;
Expand All @@ -97,8 +104,11 @@ impl Session<Initialized> {
let z = key::Key::new(prv.derive(pdh)?);
let mut nonce = [0u8; 16];
let mut iv = [0u8; 16];
rand::rand_bytes(&mut nonce)?;
rand::rand_bytes(&mut iv)?;

let mut rng: RdRand = RdRand::new()?;

rng.try_fill_bytes(&mut nonce)?;
rng.try_fill_bytes(&mut iv)?;

Ok(launch::sev::Start {
policy: self.policy,
Expand All @@ -109,14 +119,20 @@ impl Session<Initialized> {

/// Like the above start function, yet takes PDH as input instead of deriving it from a
/// certificate chain.
pub fn start_pdh(&self, pdh: certs::sev::sev::Certificate) -> Result<launch::sev::Start> {
pub fn start_pdh(
&self,
pdh: certs::sev::sev::Certificate,
) -> std::result::Result<launch::sev::Start, SessionError> {
let (crt, prv) = sev::Certificate::generate(sev::Usage::PDH)?;

let z = key::Key::new(prv.derive(&pdh)?);
let mut nonce = [0u8; 16];
let mut iv = [0u8; 16];
rand::rand_bytes(&mut nonce)?;
rand::rand_bytes(&mut iv)?;

let mut rng: RdRand = RdRand::new()?;

rng.try_fill_bytes(&mut nonce)?;
rng.try_fill_bytes(&mut iv)?;

Ok(launch::sev::Start {
policy: self.policy,
Expand Down Expand Up @@ -232,9 +248,12 @@ impl Session<Verified> {
&self,
flags: launch::sev::HeaderFlags,
data: &[u8],
) -> Result<launch::sev::Secret> {
) -> std::result::Result<launch::sev::Secret, SessionError> {
let mut iv = [0u8; 16];
rand::rand_bytes(&mut iv)?;

let mut rng: RdRand = RdRand::new()?;

rng.try_fill_bytes(&mut iv)?;

let ciphertext = symm::encrypt(symm::Cipher::aes_128_ctr(), &self.tek, Some(&iv), data)?;

Expand Down

0 comments on commit 4362d05

Please sign in to comment.