Skip to content

Commit

Permalink
Add Quote::nonce() + verify_signature() fns (#41)
Browse files Browse the repository at this point in the history
At the moment the nonce is mixed in the message and not available to api
users. There are situations in which different components validate
signature and nonce. We can expose the nonce in a non-breaking fashion.

Signed-off-by: Magnus Kulke <[email protected]>
  • Loading branch information
mkulke authored Dec 14, 2023
1 parent 79110f2 commit c40dbba
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 11 deletions.
19 changes: 16 additions & 3 deletions az-cvm-vtpm/src/vtpm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use tss_esapi::interface_types::resource_handles::NvAuth;
use tss_esapi::interface_types::session_handles::AuthSession;
use tss_esapi::structures::pcr_selection_list::PcrSelectionListBuilder;
use tss_esapi::structures::pcr_slot::PcrSlot;
use tss_esapi::structures::{AttestInfo, Data, Signature, SignatureScheme};
use tss_esapi::structures::{Attest, AttestInfo, Data, Signature, SignatureScheme};
use tss_esapi::tcti_ldr::{DeviceConfig, TctiNameConf};
use tss_esapi::traits::Marshall;
use tss_esapi::traits::{Marshall, UnMarshall};
use tss_esapi::Context;

#[cfg(feature = "verifier")]
Expand Down Expand Up @@ -119,7 +119,20 @@ pub struct Quote {
pub message: Vec<u8>,
}

/// Get a signed vTPM quote
impl Quote {
/// Extract nonce from a Quote
pub fn nonce(&self) -> Result<Vec<u8>, QuoteError> {
let attest = Attest::unmarshall(&self.message)?;
let nonce = attest.extra_data().to_vec();
Ok(nonce)
}
}

/// Get a signed vTPM Quote
///
/// # Arguments
///
/// * `data` - A byte slice to use as nonce
pub fn get_quote(data: &[u8]) -> Result<Quote, QuoteError> {
if data.len() > Data::MAX_SIZE {
return Err(QuoteError::DataTooLarge);
Expand Down
33 changes: 25 additions & 8 deletions az-cvm-vtpm/src/vtpm/verify.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use super::Quote;
use super::{Quote, QuoteError};
use openssl::hash::MessageDigest;
use openssl::pkey::{PKey, Public};
use openssl::sign::Verifier;
use thiserror::Error;
use tss_esapi::structures::Attest;
use tss_esapi::traits::UnMarshall;

#[derive(Error, Debug)]
pub enum VerifyError {
Expand All @@ -19,21 +17,40 @@ pub enum VerifyError {
SignatureMismatch,
#[error("nonce mismatch")]
NonceMismatch,
#[error("quote error")]
Quote(#[from] QuoteError),
}

impl Quote {
/// Verifies the quote's signature and nonce.
/// Verify a Quote's signature and nonce
///
/// # Arguments
///
/// * `pub_key` - A public key to verify the Quote's signature
///
/// * `nonce` - A byte slice to verify the Quote's nonce
pub fn verify(&self, pub_key: &PKey<Public>, nonce: &[u8]) -> Result<(), VerifyError> {
self.verify_signature(pub_key)?;

let quote_nonce = &self.nonce()?;
if nonce != quote_nonce {
return Err(VerifyError::NonceMismatch);
}
Ok(())
}

/// Verify a Quote's signature
///
/// # Arguments
///
/// * `pub_key` - A public key to verify the Quote's signature
pub fn verify_signature(&self, pub_key: &PKey<Public>) -> Result<(), VerifyError> {
let mut verifier = Verifier::new(MessageDigest::sha256(), pub_key)?;
verifier.update(&self.message)?;
let is_verified = verifier.verify(&self.signature)?;
if !is_verified {
return Err(VerifyError::SignatureMismatch);
}
let attest = Attest::unmarshall(&self.message)?;
if nonce != attest.extra_data().as_slice() {
return Err(VerifyError::NonceMismatch);
}
Ok(())
}
}
Expand Down

0 comments on commit c40dbba

Please sign in to comment.