Skip to content

Commit 68a4c17

Browse files
committed
improve quote parser validation
Signed-off-by: Jun Kimura <jun.kimura@datachain.jp>
1 parent 617f30e commit 68a4c17

File tree

5 files changed

+171
-59
lines changed

5 files changed

+171
-59
lines changed

crates/types/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ pub const ECDSA_256_WITH_P256_CURVE: u16 = 2;
2020
pub const INTEL_QE_VENDOR_ID: [u8; 16] = [
2121
0x93, 0x9A, 0x72, 0x33, 0xF7, 0x9C, 0x4C, 0xA9, 0x94, 0x0A, 0x0D, 0xB3, 0x95, 0x7F, 0x06, 0x07,
2222
];
23+
/// ref. p.67 <https://download.01.org/intel-sgx/sgx-dcap/1.22/linux/docs/Intel_SGX_ECDSA_QuoteLibReference_DCAP_API.pdf>
24+
pub const QUOTE_HEADER_LEN: usize = 48;
2325
/// ref. p.69 <https://download.01.org/intel-sgx/sgx-dcap/1.22/linux/docs/Intel_SGX_ECDSA_QuoteLibReference_DCAP_API.pdf>
2426
pub const ENCLAVE_REPORT_LEN: usize = 384;
2527
/// ref. p.37 <https://download.01.org/intel-sgx/sgx-dcap/1.22/linux/docs/Intel_TDX_DCAP_Quoting_Library_API.pdf>

crates/types/src/quotes/body.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use anyhow::bail;
22

3-
use crate::Result;
3+
use crate::{Result, ENCLAVE_REPORT_LEN};
44

55
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
66
pub enum QuoteBody {
@@ -59,7 +59,7 @@ pub struct EnclaveReport {
5959
impl EnclaveReport {
6060
/// Parse raw bytes into EnclaveReport
6161
pub fn from_bytes(raw_bytes: &[u8]) -> Result<EnclaveReport> {
62-
if raw_bytes.len() != 384 {
62+
if raw_bytes.len() != ENCLAVE_REPORT_LEN {
6363
bail!("Invalid length of bytes for EnclaveReport");
6464
}
6565
let mut obj = EnclaveReport {
@@ -341,7 +341,7 @@ pub(crate) mod tests {
341341
}
342342

343343
// proptest strategy for EnclaveReport
344-
pub fn enclave_report_strategy() -> impl Strategy<Value = EnclaveReport> {
344+
pub(crate) fn enclave_report_strategy() -> impl Strategy<Value = EnclaveReport> {
345345
(
346346
any::<[u8; 16]>(),
347347
any::<[u8; 4]>(),
@@ -388,7 +388,7 @@ pub(crate) mod tests {
388388
}
389389

390390
// proptest strategy for TD10ReportBody
391-
fn td10_report_body_strategy() -> impl Strategy<Value = TD10ReportBody> {
391+
pub(crate) fn td10_report_body_strategy() -> impl Strategy<Value = TD10ReportBody> {
392392
(
393393
(
394394
any::<[u8; 16]>(),

crates/types/src/quotes/mod.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
utils::{parse_x509_der_multi, pem_to_der},
3-
Result,
3+
Result, QUOTE_HEADER_LEN,
44
};
55

66
pub mod body;
@@ -25,7 +25,7 @@ pub enum Quote {
2525
impl Quote {
2626
/// Parse a byte slice into a `Quote` structure.
2727
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
28-
if bytes.len() < 48 {
28+
if bytes.len() < QUOTE_HEADER_LEN {
2929
bail!("Invalid quote length");
3030
}
3131
let version = u16::from_le_bytes([bytes[0], bytes[1]]);
@@ -81,8 +81,8 @@ pub struct QuoteHeader {
8181
impl QuoteHeader {
8282
/// Parse a QuoteHeader from a byte slice.
8383
pub fn from_bytes(raw_bytes: &[u8]) -> Result<Self> {
84-
if raw_bytes.len() < 48 {
85-
return Err(anyhow::anyhow!("QuoteHeader is too short"));
84+
if raw_bytes.len() != QUOTE_HEADER_LEN {
85+
return Err(anyhow::anyhow!("Invalid QuoteHeader length"));
8686
}
8787
let version = u16::from_le_bytes([raw_bytes[0], raw_bytes[1]]);
8888
let att_key_type = u16::from_le_bytes([raw_bytes[2], raw_bytes[3]]);
@@ -186,6 +186,16 @@ pub struct CertData {
186186
}
187187

188188
impl CertData {
189+
/// Create a new CertData instance.
190+
pub fn new(cert_data_type: u16, cert_data: Vec<u8>) -> Self {
191+
let cert_data_size = cert_data.len() as u32;
192+
CertData {
193+
cert_data_type,
194+
cert_data_size,
195+
cert_data,
196+
}
197+
}
198+
189199
/// Parse a CertData from a byte slice.
190200
pub fn from_bytes(raw_bytes: &[u8]) -> Result<Self> {
191201
let len = raw_bytes.len();
@@ -322,7 +332,7 @@ pub(crate) mod tests {
322332

323333
proptest! {
324334
#[test]
325-
fn test_quote_header_roundtrip(quote_header in quote_header_strategy(None)) {
335+
fn test_quote_header_roundtrip(quote_header in quote_header_strategy(None, None)) {
326336
let raw_bytes = quote_header.to_bytes();
327337
let parsed_quote_header = QuoteHeader::from_bytes(&raw_bytes).unwrap();
328338
prop_assert_eq!(quote_header, parsed_quote_header, "raw_bytes: {:?}", raw_bytes);
@@ -352,6 +362,7 @@ pub(crate) mod tests {
352362

353363
pub(crate) fn quote_header_strategy(
354364
version: Option<u16>,
365+
tee_type: Option<u32>,
355366
) -> impl Strategy<Value = QuoteHeader> {
356367
(
357368
any::<u16>(),
@@ -366,7 +377,7 @@ pub(crate) mod tests {
366377
move |(
367378
version_,
368379
att_key_type,
369-
tee_type,
380+
tee_type_,
370381
qe_svn,
371382
pce_svn,
372383
qe_vendor_id,
@@ -375,7 +386,7 @@ pub(crate) mod tests {
375386
QuoteHeader {
376387
version: version.unwrap_or(version_),
377388
att_key_type,
378-
tee_type,
389+
tee_type: tee_type.unwrap_or(tee_type_),
379390
qe_svn,
380391
pce_svn,
381392
qe_vendor_id,

crates/types/src/quotes/version_3.rs

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
use super::{body::EnclaveReport, CertData, QeAuthData, QuoteHeader};
2-
use crate::Result;
3-
use anyhow::anyhow;
2+
use crate::{Result, ENCLAVE_REPORT_LEN, QUOTE_HEADER_LEN};
3+
use anyhow::{anyhow, bail};
4+
5+
const SIGNATURE_DATA_SIZE_OFFSET: usize = QUOTE_HEADER_LEN + ENCLAVE_REPORT_LEN;
6+
const SIGNATURE_DATA_SIZE_LEN: usize = 4;
7+
const SIGNATURE_DATA_OFFSET: usize =
8+
QUOTE_HEADER_LEN + ENCLAVE_REPORT_LEN + SIGNATURE_DATA_SIZE_LEN;
49

510
/// Quote structure for DCAP version 3.
611
/// The structure is defined in the Intel SGX ECDSA Quote Library Reference.
@@ -29,30 +34,31 @@ pub struct QuoteV3 {
2934
impl QuoteV3 {
3035
/// Parse a QuoteV3 from a byte slice.
3136
pub fn from_bytes(raw_bytes: &[u8]) -> Result<QuoteV3> {
32-
if raw_bytes.len() < 436 {
33-
return Err(anyhow!("QuoteV3 data is too short"));
37+
if raw_bytes.len() < SIGNATURE_DATA_OFFSET {
38+
bail!("QuoteV3 data is too short");
3439
}
35-
let header = QuoteHeader::from_bytes(&raw_bytes[0..48])?;
40+
let header = QuoteHeader::from_bytes(&raw_bytes[..QUOTE_HEADER_LEN])?;
3641
if header.version != 3 {
37-
return Err(anyhow!("QuoteV3 version is not 3"));
42+
bail!("QuoteV3 version is not 3");
3843
}
39-
let isv_enclave_report = EnclaveReport::from_bytes(&raw_bytes[48..432])?;
44+
let isv_enclave_report =
45+
EnclaveReport::from_bytes(&raw_bytes[QUOTE_HEADER_LEN..SIGNATURE_DATA_SIZE_OFFSET])?;
4046
let signature_len = u32::from_le_bytes([
41-
raw_bytes[432],
42-
raw_bytes[433],
43-
raw_bytes[434],
44-
raw_bytes[435],
47+
raw_bytes[SIGNATURE_DATA_SIZE_OFFSET],
48+
raw_bytes[SIGNATURE_DATA_SIZE_OFFSET + 1],
49+
raw_bytes[SIGNATURE_DATA_SIZE_OFFSET + 2],
50+
raw_bytes[SIGNATURE_DATA_SIZE_OFFSET + 3],
4551
]);
46-
if raw_bytes.len() != 436 + signature_len as usize {
47-
return Err(anyhow!(
52+
if raw_bytes.len() < SIGNATURE_DATA_OFFSET + signature_len as usize {
53+
bail!(
4854
"QuoteV3 data is not the expected length: expected {}, got {}",
49-
436 + signature_len,
55+
SIGNATURE_DATA_OFFSET + signature_len as usize,
5056
raw_bytes.len()
51-
));
57+
);
5258
}
53-
// allocate and create a buffer for signature
54-
let signature_slice = &raw_bytes[436..436 + signature_len as usize];
55-
let signature = QuoteSignatureDataV3::from_bytes(signature_slice)?;
59+
let signature = QuoteSignatureDataV3::from_bytes(
60+
&raw_bytes[SIGNATURE_DATA_OFFSET..SIGNATURE_DATA_OFFSET + signature_len as usize],
61+
)?;
5662

5763
Ok(QuoteV3 {
5864
header,
@@ -130,10 +136,13 @@ impl QuoteSignatureDataV3 {
130136
#[cfg(test)]
131137
mod tests {
132138
use super::*;
133-
use crate::quotes::{
134-
body::tests::enclave_report_strategy,
135-
tests::{cert_data_strategy, qe_auth_data_strategy, quote_header_strategy},
136-
Quote,
139+
use crate::{
140+
quotes::{
141+
body::tests::enclave_report_strategy,
142+
tests::{cert_data_strategy, qe_auth_data_strategy, quote_header_strategy},
143+
Quote,
144+
},
145+
SGX_TEE_TYPE,
137146
};
138147
use proptest::{collection::vec, prelude::*};
139148

@@ -174,7 +183,7 @@ mod tests {
174183

175184
pub(crate) fn quote_v3_strategy() -> impl Strategy<Value = QuoteV3> {
176185
(
177-
quote_header_strategy(Some(3)),
186+
quote_header_strategy(Some(3), Some(SGX_TEE_TYPE)),
178187
enclave_report_strategy(),
179188
quote_signature_data_v3_strategy(),
180189
)

0 commit comments

Comments
 (0)