Skip to content

Commit

Permalink
Add capabilities_negotiation structures
Browse files Browse the repository at this point in the history
This change aims to include those structures
that will be required to communicate
capabilities negotiation information for
Keylime Push model

Signed-off-by: Sergio Arroutbi <sarroutb@redhat.com>
  • Loading branch information
sarroutbi committed Feb 24, 2025
1 parent 3b6c0ff commit 105cfde
Show file tree
Hide file tree
Showing 3 changed files with 357 additions and 0 deletions.
1 change: 1 addition & 0 deletions keylime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod ip_parser;
pub mod list_parser;
pub mod registrar_client;
pub mod serialization;
pub mod structures;
pub mod tpm;
pub mod version;

Expand Down
353 changes: 353 additions & 0 deletions keylime/src/structures/capabilities_negotiation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,353 @@
use serde::{Deserialize, Serialize};

// Define the structure for the AttestationRequest:
#[derive(Serialize, Deserialize, Debug)]
pub struct AttestationRequest {
#[serde(rename(serialize = "data", deserialize = "data"))]
pub data: RequestData,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct RequestData {
#[serde(rename(serialize = "type", deserialize = "type"))]
pub type_: String,
pub attributes: Attributes,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Attributes {
pub evidence_supported: Vec<EvidenceSupported>,
pub boot_time: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct EvidenceSupported {
pub evidence_class: String,
pub evidence_type: String,
pub agent_capabilities: AgentCapabilities,
pub version: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct AgentCapabilities {
pub spec_version: String,
pub hash_algorithms: Vec<String>,
pub signing_schemes: Vec<String>,
pub attestation_keys: Vec<AttestationKeys>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct AttestationKeys {
pub key_class: String,
pub key_identifier: String,
pub key_algorithm: String,
pub public_hash: String,
}

// Define the structure for the AttestationResponse:
#[derive(Serialize, Deserialize, Debug)]
pub struct AttestationResponse {
#[serde(rename(serialize = "data", deserialize = "data"))]
pub data: ResponseData,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ResponseData {
#[serde(rename(serialize = "type", deserialize = "type"))]
pub type_: String,
pub attributes: ResponseAttributes,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ResponseAttributes {
pub evidence_collected: Vec<EvidenceCollected>,
pub boot_time: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct EvidenceCollected {
pub evidence_class: String,
pub evidence_type: String,
pub chosen_parameters: ChosenParameters,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ChosenParameters {
pub nonce: String,
pub pcr_selection: Vec<i32>,
pub hash_algorithm: String,
pub signing_scheme: String,
pub attestation_key: AttestationKey,
pub starting_offset: Option<i32>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct AttestationKey {
pub key_class: String,
pub key_identifier: String,
pub key_algorithm: String,
pub public_hash: String,
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn serialize_request() {
// Create a new AttestationRequest object and serialize it to JSON
let request = AttestationRequest {
data: RequestData {
type_: "attestation".to_string(),
attributes: Attributes {
evidence_supported: vec![
EvidenceSupported {
evidence_class: "certification".to_string(),
evidence_type: "tpm_quote".to_string(),
agent_capabilities: AgentCapabilities {
spec_version: "2.0".to_string(),
hash_algorithms: vec!["sha3_512".to_string()],
signing_schemes: vec!["rsassa".to_string()],
attestation_keys: vec![
AttestationKeys {
key_class: "private_key".to_string(),
key_identifier: "att_key_identifier".to_string(),
key_algorithm: "rsa".to_string(),
public_hash: "cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411".to_string(),
},
],
},
version: Some("2.1".to_string()),
},
],
boot_time: "2024-11-12T16:21:17Z".to_string(),
},
},
};
let json = serde_json::to_string(&request).unwrap(); //#[allow_ci]
println!("{}", json);
assert_eq!(
json,
r#"{"data":{"type":"attestation","attributes":{"evidence_supported":[{"evidence_class":"certification","evidence_type":"tpm_quote","agent_capabilities":{"spec_version":"2.0","hash_algorithms":["sha3_512"],"signing_schemes":["rsassa"],"attestation_keys":[{"key_class":"private_key","key_identifier":"att_key_identifier","key_algorithm":"rsa","public_hash":"cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411"}]},"version":"2.1"}],"boot_time":"2024-11-12T16:21:17Z"}}}"#
);
}

#[test]
fn deserialize_request() {
// Create a JSON string and deserialize it to an AttestationRequest object
let json = r#"
{
"data": {
"type":"attestation",
"attributes": {
"evidence_supported":[{"evidence_class":"certification",
"evidence_type":"tpm_quote",
"agent_capabilities":{"spec_version":"2.0",
"hash_algorithms":["sha3_512"],
"signing_schemes":["rsassa"],
"attestation_keys":[{"key_class":"private_key","key_identifier":"att_key_identifier",
"key_algorithm":"rsa",
"public_hash":"cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411"}]},
"version":"2.1"}],
"boot_time":"2024-11-12T16:21:17Z"
}
}
}"#;
let request: AttestationRequest = serde_json::from_str(json).unwrap(); //#[allow_ci]
assert_eq!(request.data.type_, "attestation");
assert_eq!(
request.data.attributes.evidence_supported[0].evidence_class,
"certification"
);
assert_eq!(
request.data.attributes.evidence_supported[0].version,
Some("2.1".to_string())
);
assert_eq!(
request.data.attributes.evidence_supported[0].evidence_type,
"tpm_quote"
);
assert_eq!(
request.data.attributes.evidence_supported[0]
.agent_capabilities
.spec_version,
"2.0"
);
assert_eq!(
request.data.attributes.evidence_supported[0]
.agent_capabilities
.hash_algorithms[0],
"sha3_512"
);
assert_eq!(
request.data.attributes.evidence_supported[0]
.agent_capabilities
.signing_schemes[0],
"rsassa"
);
assert_eq!(
request.data.attributes.evidence_supported[0]
.agent_capabilities
.attestation_keys[0]
.key_class,
"private_key"
);
assert_eq!(
request.data.attributes.evidence_supported[0]
.agent_capabilities
.attestation_keys[0]
.key_identifier,
"att_key_identifier"
);
assert_eq!(
request.data.attributes.evidence_supported[0]
.agent_capabilities
.attestation_keys[0]
.key_algorithm,
"rsa"
);
assert_eq!(
request.data.attributes.evidence_supported[0]
.agent_capabilities
.attestation_keys[0]
.public_hash,
"cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411"
);
assert_eq!(request.data.attributes.boot_time, "2024-11-12T16:21:17Z");
}

#[test]
fn serialize_response() {
// Create a new AttestationResponse object and serialize it to JSON
let response = AttestationResponse {
data: ResponseData {
type_: "attestation".to_string(),
attributes: ResponseAttributes {
evidence_collected: vec![
EvidenceCollected {
evidence_class: "certification".to_string(),
evidence_type: "tpm_quote".to_string(),
chosen_parameters: ChosenParameters {
nonce: "nonce".to_string(),
pcr_selection: vec![0],
hash_algorithm: "sha384".to_string(),
signing_scheme: "rsassa".to_string(),
attestation_key: AttestationKey {
key_class: "private_key".to_string(),
key_identifier: "att_key_identifier".to_string(),
key_algorithm: "rsa".to_string(),
public_hash: "cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411".to_string(),
},
starting_offset: Some(25),
},
},
],
boot_time: "2024-11-12T16:21:17Z".to_string(),
},
},
};
let json = serde_json::to_string(&response).unwrap(); //#[allow_ci]
println!("{}", json);
assert_eq!(
json,
r#"{"data":{"type":"attestation","attributes":{"evidence_collected":[{"evidence_class":"certification","evidence_type":"tpm_quote","chosen_parameters":{"nonce":"nonce","pcr_selection":[0],"hash_algorithm":"sha384","signing_scheme":"rsassa","attestation_key":{"key_class":"private_key","key_identifier":"att_key_identifier","key_algorithm":"rsa","public_hash":"cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411"},"starting_offset":25}}],"boot_time":"2024-11-12T16:21:17Z"}}}"#
);
}

#[test]
fn deserialize_response() {
// Create a JSON string and deserialize it to an AttestationResponse object
let json = r#"
{
"data": {
"type":"attestation",
"attributes": {
"evidence_collected":[{"evidence_class":"certification",
"evidence_type":"tpm_quote",
"chosen_parameters":{"nonce":"nonce",
"pcr_selection":[0],
"hash_algorithm":"sha384",
"signing_scheme":"rsassa",
"attestation_key":{"key_class":"private_key",
"key_identifier":"att_key_identifier",
"key_algorithm":"rsa",
"public_hash":"cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411"},
"starting_offset":25}}],
"boot_time":"2024-11-12T16:21:17Z"
}
}
}"#;
let response: AttestationResponse =
serde_json::from_str(json).unwrap(); //#[allow_ci]
assert_eq!(response.data.type_, "attestation");
assert_eq!(
response.data.attributes.evidence_collected[0].evidence_class,
"certification"
);
assert_eq!(
response.data.attributes.evidence_collected[0].evidence_type,
"tpm_quote"
);
assert_eq!(
response.data.attributes.evidence_collected[0]
.chosen_parameters
.nonce,
"nonce"
);
assert_eq!(
response.data.attributes.evidence_collected[0]
.chosen_parameters
.pcr_selection[0],
0
);
assert_eq!(
response.data.attributes.evidence_collected[0]
.chosen_parameters
.hash_algorithm,
"sha384"
);
assert_eq!(
response.data.attributes.evidence_collected[0]
.chosen_parameters
.signing_scheme,
"rsassa"
);
assert_eq!(
response.data.attributes.evidence_collected[0]
.chosen_parameters
.attestation_key
.key_class,
"private_key"
);
assert_eq!(
response.data.attributes.evidence_collected[0]
.chosen_parameters
.attestation_key
.key_identifier,
"att_key_identifier"
);
assert_eq!(
response.data.attributes.evidence_collected[0]
.chosen_parameters
.attestation_key
.key_algorithm,
"rsa"
);
assert_eq!(
response.data.attributes.evidence_collected[0]
.chosen_parameters
.attestation_key
.public_hash,
"cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411"
);
assert_eq!(
response.data.attributes.evidence_collected[0]
.chosen_parameters
.starting_offset,
Some(25)
);
assert_eq!(
response.data.attributes.boot_time,
"2024-11-12T16:21:17Z"
);
}
}
3 changes: 3 additions & 0 deletions keylime/src/structures/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod capabilities_negotiation;

pub use capabilities_negotiation::*;

0 comments on commit 105cfde

Please sign in to comment.