diff --git a/cca_token_demo.sh b/cca_token_demo.sh new file mode 100755 index 0000000..9e0e6a0 --- /dev/null +++ b/cca_token_demo.sh @@ -0,0 +1,161 @@ +#!/bin/bash + +# CCA Token Demo Script +# This script demonstrates common operations with the ccatoken CLI tool + +set -e # Exit on any error +set -u # Treat unset variables as errors + +# Define colors for better output formatting +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print section headers +print_header() { + echo -e "\n${BLUE}=========================================================${NC}" + echo -e "${BLUE}$1${NC}" + echo -e "${BLUE}=========================================================${NC}\n" +} + +# Function to print success messages +print_success() { + echo -e "${GREEN}✓ $1${NC}" +} + +# Function to print error messages +print_error() { + echo -e "${RED}✗ $1${NC}" + return 1 +} + +# Function to print info messages +print_info() { + echo -e "${YELLOW}ℹ $1${NC}" +} + +# Make sure we're in the project directory +cd "$(dirname "$0")" + +# Check if the ccatoken binary exists and is in the PATH +check_ccatoken() { + print_header "Checking ccatoken binary" + + if ! command -v ccatoken &> /dev/null; then + print_info "Building ccatoken binary" + cargo build || print_error "Failed to build ccatoken" + export PATH=$PATH:"$PWD/target/debug" + fi + + if command -v ccatoken &> /dev/null; then + print_success "ccatoken binary found in PATH" + else + print_error "ccatoken binary not found in PATH. Make sure to build the project first." + fi +} + +# Verify a CCA token using trust anchors +verify_token() { + print_header "Verifying CCA Token" + + local token_file="$1" + local tastore_file="$2" + + print_info "Verifying token: $token_file with trust anchor store: $tastore_file" + + if ccatoken verify -e "$token_file" -t "$tastore_file"; then + print_success "Token verification successful" + else + print_error "Token verification failed" + fi +} + +# Appraise a CCA token using reference values +appraise_token() { + print_header "Appraising CCA Token" + + local token_file="$1" + local rvstore_file="$2" + + print_info "Appraising token: $token_file with reference value store: $rvstore_file" + + if ccatoken appraise -e "$token_file" -r "$rvstore_file"; then + print_success "Token appraisal successful" + else + print_error "Token appraisal failed" + fi +} + +# Extract golden values from a CCA token +extract_golden_values() { + print_header "Extracting Golden Values" + + local token_file="$1" + local cpak_file="$2" + local tastore_output="golden-tastore.json" + local rvstore_output="golden-rvstore.json" + + print_info "Extracting golden values from token: $token_file with CPAK: $cpak_file" + + if ccatoken golden -e "$token_file" -c "$cpak_file" -t "$tastore_output" -r "$rvstore_output"; then + print_success "Golden values extraction successful" + print_info "Trust anchors saved to: $tastore_output" + print_info "Reference values saved to: $rvstore_output" + + # Pretty print the golden values (if jq is available) + if command -v jq &> /dev/null; then + echo -e "\n${YELLOW}Trust Anchor Store Content:${NC}" + jq . "$tastore_output" + + echo -e "\n${YELLOW}Reference Value Store Content:${NC}" + jq . "$rvstore_output" + fi + else + print_error "Golden values extraction failed" + fi +} + +# List available test tokens +list_test_tokens() { + print_header "Available Test Tokens" + + echo "CBOR Test Tokens:" + find testdata -name "*.cbor" | sort + + echo -e "\nDiagnostic Format Tokens:" + find testdata -name "*.diag" | sort +} + +# Main function +main() { + # Check if ccatoken binary is available + check_ccatoken + + # Example usage with test data + print_header "CCA Token Demo" + + # List available test tokens + list_test_tokens + + # Default test files + local default_token="testdata/cca-token-01.cbor" + local default_cpak="testdata/cpak.json" + local default_tastore="testdata/ta.json" + local default_rvstore="testdata/rv.json" + + # Run verification with default test files + verify_token "$default_token" "$default_tastore" + + # Run appraisal with default test files + appraise_token "$default_token" "$default_rvstore" + + # Extract golden values with default test files + extract_golden_values "$default_token" "$default_cpak" + + print_header "Demo completed successfully!" +} + +# Run the main function +main \ No newline at end of file diff --git a/docs/TEST_PLAN.md b/docs/TEST_PLAN.md new file mode 100644 index 0000000..22cbd2d --- /dev/null +++ b/docs/TEST_PLAN.md @@ -0,0 +1,396 @@ +# Test Plan for rust-ccatoken + +This document defines a comprehensive test plan for the `rust-ccatoken` library. The plan covers the three main functional areas of the library: + +1. CBOR Decoding +2. Cryptographic Verification +3. Appraisal + +For each area, we define a set of test cases with descriptions, test vectors, and expected outcomes. + +## 1. CBOR Decoding Tests + +These tests verify the library's ability to correctly parse and decode CCA tokens from their CBOR-encoded format. + +### 1.1 Valid Token Decoding + +**Description**: Verify that a well-formed CCA token can be successfully decoded. + +**Test Vectors**: +- `testdata/cca-token-01.cbor`: Standard valid CCA token +- `testdata/cca-token-02.cbor`: Alternative valid CCA token format +- `testdata/cca-token-draft-ffm-00.cbor`: Draft FFM format token + +**Expected Outcome**: All tokens should be successfully decoded without errors, with correct extraction of platform and realm claims. + +```rust +// Test code example +let token = include_bytes!("../../testdata/cca-token-01.cbor"); +let evidence = Evidence::decode(token.as_slice()); +assert!(evidence.is_ok()); +``` + +### 1.2 Platform Token Decoding + +**Description**: Verify decoding of platform-specific token components. + +**Test Vectors**: +- `testdata/platform-claims.cbor`: Platform claims CBOR data + +**Expected Outcome**: Platform-specific fields should be correctly parsed: +- Implementation ID +- Instance ID +- Platform configuration +- SW components +- Challenge + +```rust +// Test code example +let platform_claims = include_bytes!("../../testdata/platform-claims.cbor"); +let platform = Platform::decode(platform_claims); +assert!(platform.is_ok()); +assert_eq!(platform.unwrap().profile, "http://arm.com/CCA-SSD/1.0.0"); +``` + +### 1.3 Realm Token Decoding + +**Description**: Verify decoding of realm-specific token components. + +**Test Vectors**: +- `testdata/realm-claims.cbor`: Realm claims CBOR data + +**Expected Outcome**: Realm-specific fields should be correctly parsed: +- Initial measurement +- RAK hash algorithm +- Extensible measurements +- Personalization value + +```rust +// Test code example +let realm_claims = include_bytes!("../../testdata/realm-claims.cbor"); +let realm = Realm::decode(realm_claims); +assert!(realm.is_ok()); +``` + +### 1.4 Malformed Token Handling + +**Description**: Verify handling of tokens with malformed structures. + +**Test Vectors**: +- `testdata/realm-claims-missing-challenge.cbor`: Realm claims with missing challenge field +- `testdata/realm-claims+spurious-numeric-key.cbor`: Realm claims with additional unexpected numeric key +- `testdata/realm-claims+spurious-text-key.cbor`: Realm claims with additional unexpected text key + +**Expected Outcome**: +- Missing required fields should result in appropriate error +- Spurious fields should be handled gracefully according to the specification + +```rust +// Test code example +let malformed_token = include_bytes!("../../testdata/realm-claims-missing-challenge.cbor"); +let result = Realm::decode(malformed_token); +// Should return an appropriate error for the missing field +assert!(matches!(result, Err(Error::MissingClaim(_)))); +``` + +### 1.5 Token Collection Decoding + +**Description**: Verify decoding of an entire token collection (both platform and realm tokens). + +**Test Vectors**: +- `testdata/cca-token-01.cbor`: Complete token collection + +**Expected Outcome**: Both platform and realm tokens should be extracted and decoded correctly from the collection. + +```rust +// Test code example +let token_collection = include_bytes!("../../testdata/cca-token-01.cbor"); +let evidence = Evidence::decode(token_collection.as_slice()).unwrap(); +assert!(!evidence.platform.bytes.is_empty()); +assert!(!evidence.realm.bytes.is_empty()); +``` + +## 2. Cryptographic Verification Tests + +These tests verify the library's ability to cryptographically validate CCA tokens. + +### 2.1 Valid Token Verification + +**Description**: Verify that a legitimate token with valid signatures can be successfully verified. + +**Test Vectors**: +- Token: `testdata/cca-token-01.cbor` +- Trust Anchor Store: `testdata/ta.json` + +**Expected Outcome**: The token should be verified successfully with both platform and realm trust vectors set to `TRUSTWORTHY_INSTANCE`. + +```rust +// Test code example +let token = include_bytes!("../../testdata/cca-token-01.cbor"); +let mut evidence = Evidence::decode(token.as_slice()).unwrap(); + +let ta_json = include_str!("../../testdata/ta.json"); +let mut tas = MemoTrustAnchorStore::new(); +tas.load_json(ta_json).unwrap(); + +let result = evidence.verify(&tas); +assert!(result.is_ok()); +assert_eq!(evidence.platform_tvec.instance_identity, TRUSTWORTHY_INSTANCE); +assert_eq!(evidence.realm_tvec.instance_identity, TRUSTWORTHY_INSTANCE); +``` + +### 2.2 Invalid Platform Signature + +**Description**: Verify handling of tokens with invalid platform signatures. + +**Test Vectors**: +- Token: `testdata/cca-token-02.cbor` +- Trust Anchor Store: `testdata/ta-02-bad.json` (contains incorrect CPAK) + +**Expected Outcome**: The verification should set the platform trust vector to `CRYPTO_VALIDATION_FAILED` and the realm trust vector to `NO_CLAIM`. + +```rust +// Test code example +let token = include_bytes!("../../testdata/cca-token-02.cbor"); +let mut evidence = Evidence::decode(token.as_slice()).unwrap(); + +let ta_json = include_str!("../../testdata/ta-02-bad.json"); +let mut tas = MemoTrustAnchorStore::new(); +tas.load_json(ta_json).unwrap(); + +let result = evidence.verify(&tas); +assert!(result.is_ok()); // Function succeeds but sets error in trust vector +assert_eq!(evidence.platform_tvec.instance_identity, CRYPTO_VALIDATION_FAILED); +assert_eq!(evidence.realm_tvec.instance_identity, NO_CLAIM); +``` + +### 2.3 Invalid Realm Signature + +**Description**: Verify handling of tokens with invalid realm signatures. + +**Test Vectors**: +- Token: `testdata/bug-33-repro.cbor` (contains correctly signed platform but incorrectly signed realm) +- Trust Anchor Store: `testdata/ta-tfa.json` + +**Expected Outcome**: The verification should set the platform trust vector to `TRUSTWORTHY_INSTANCE` and the realm trust vector to `CRYPTO_VALIDATION_FAILED`. + +```rust +// Test code example +let token = include_bytes!("../../testdata/bug-33-repro.cbor"); +let mut evidence = Evidence::decode(token.as_slice()).unwrap(); + +let ta_json = include_str!("../../testdata/ta-tfa.json"); +let mut tas = MemoTrustAnchorStore::new(); +tas.load_json(ta_json).unwrap(); + +let result = evidence.verify(&tas); +assert!(result.is_ok()); // Function succeeds but sets error in trust vector +assert_eq!(evidence.platform_tvec.instance_identity, TRUSTWORTHY_INSTANCE); +assert_eq!(evidence.realm_tvec.instance_identity, CRYPTO_VALIDATION_FAILED); +``` + +### 2.4 Invalid Binding + +**Description**: Verify handling of tokens with invalid binding between platform and realm. + +**Test Vectors**: +- A token where the platform's challenge does not match the hash of the realm's public key + +**Expected Outcome**: The verification should set the realm trust vector to `CRYPTO_VALIDATION_FAILED`. + +### 2.5 Trust Anchor Store Integration + +**Description**: Verify the integration with the trust anchor store for CPAK lookup. + +**Test Vectors**: +- Token: `testdata/cca-token-01.cbor` +- Trust Anchor Store: `testdata/ta.json` + +**Expected Outcome**: The correct CPAK should be retrieved from the trust store based on the platform's implementation ID. + +```rust +// Test code example +let token = include_bytes!("../../testdata/cca-token-01.cbor"); +let mut evidence = Evidence::decode(token.as_slice()).unwrap(); + +let ta_json = include_str!("../../testdata/ta.json"); +let mut tas = MemoTrustAnchorStore::new(); +tas.load_json(ta_json).unwrap(); + +// Should retrieve the correct CPAK and not return an error +let result = evidence.verify(&tas); +assert!(result.is_ok()); +``` + +## 3. Appraisal Tests + +These tests verify the library's ability to appraise CCA tokens against reference values. + +### 3.1 Successful Appraisal + +**Description**: Verify that a token can be successfully appraised against matching reference values. + +**Test Vectors**: +- Token: `testdata/cca-token-01.cbor` +- Reference Value Store: `testdata/rv.json` + +**Expected Outcome**: Both platform and realm should be appraised successfully with trust vectors indicating `TRUSTWORTHY_INSTANCE`. + +```rust +// Test code example +let token = include_bytes!("../../testdata/cca-token-01.cbor"); +let mut evidence = Evidence::decode(token.as_slice()).unwrap(); + +let rv_json = include_str!("../../testdata/rv.json"); +let mut rvs = MemoRefValueStore::new(); +rvs.load_json(rv_json).unwrap(); + +let result = evidence.appraise(&rvs); +assert!(result.is_ok()); +// Check trust vectors have been set correctly +assert!(evidence.platform_tvec.instance_identity.get() == TRUSTWORTHY_INSTANCE); +assert!(evidence.realm_tvec.instance_identity.get() == TRUSTWORTHY_INSTANCE); +``` + +### 3.2 Platform Implementation ID Mismatch + +**Description**: Verify handling when the platform implementation ID does not match any reference values. + +**Test Vectors**: +- A token with an implementation ID that doesn't match any in the reference value store + +**Expected Outcome**: The platform trust vector should be set to `REFERENCE_VALUE_MISMATCH`. + +### 3.3 Platform Software Component Mismatch + +**Description**: Verify handling when a platform software component doesn't match reference values. + +**Test Vectors**: +- A token with software component measurements that don't match the reference values + +**Expected Outcome**: The platform trust vector should be set to `REFERENCE_VALUE_MISMATCH`. + +### 3.4 Realm Initial Measurement Mismatch + +**Description**: Verify handling when the realm initial measurement doesn't match the reference value. + +**Test Vectors**: +- A token with a realm initial measurement that doesn't match the reference value + +**Expected Outcome**: The realm trust vector should be set to `REFERENCE_VALUE_MISMATCH`. + +### 3.5 Realm Extensible Measurement Mismatch + +**Description**: Verify handling when a realm extensible measurement doesn't match the reference value. + +**Test Vectors**: +- A token with realm extensible measurements that don't match the reference values + +**Expected Outcome**: The realm trust vector should be set to `REFERENCE_VALUE_MISMATCH`. + +### 3.6 Unknown Reference Values + +**Description**: Verify handling when no reference values can be found for the token. + +**Test Vectors**: +- An empty reference value store + +**Expected Outcome**: The trust vectors should be set to `REFERENCE_VALUE_MISSING`. + +## 4. End-to-End Tests + +These tests verify the complete flow from decoding to verification to appraisal. + +### 4.1 Complete Flow with Valid Token + +**Description**: Verify the complete flow of decoding, verifying, and appraising a valid token. + +**Test Vectors**: +- Token: `testdata/cca-token-01.cbor` +- Trust Anchor Store: `testdata/ta.json` +- Reference Value Store: `testdata/rv.json` + +**Expected Outcome**: The token should be successfully decoded, verified, and appraised with both trust vectors indicating `TRUSTWORTHY_INSTANCE`. + +```rust +// Test code example +let token = include_bytes!("../../testdata/cca-token-01.cbor"); +let mut evidence = Evidence::decode(token.as_slice()).unwrap(); + +// Verify the token +let ta_json = include_str!("../../testdata/ta.json"); +let mut tas = MemoTrustAnchorStore::new(); +tas.load_json(ta_json).unwrap(); +evidence.verify(&tas).unwrap(); + +// Appraise the token +let rv_json = include_str!("../../testdata/rv.json"); +let mut rvs = MemoRefValueStore::new(); +rvs.load_json(rv_json).unwrap(); +evidence.appraise(&rvs).unwrap(); + +// Check final trust vectors +assert_eq!(evidence.platform_tvec.instance_identity, TRUSTWORTHY_INSTANCE); +assert_eq!(evidence.realm_tvec.instance_identity, TRUSTWORTHY_INSTANCE); +``` + +### 4.2 Golden Value Extraction + +**Description**: Verify the extraction of golden values from a valid token. + +**Test Vectors**: +- Token: `testdata/cca-token-01.cbor` +- CPAK: `testdata/cpak.json` + +**Expected Outcome**: Reference values and trust anchors should be successfully extracted from the token. + +```rust +// Similar to the golden() function in main.rs +let token = include_bytes!("../../testdata/cca-token-01.cbor"); +let mut evidence = Evidence::decode(token.as_slice()).unwrap(); + +let cpak_json = include_str!("../../testdata/cpak.json"); +let cpak = map_str_to_cpak(&evidence.platform_claims, cpak_json).unwrap(); + +evidence.verify_with_cpak(cpak).unwrap(); + +// Extract reference values and trust anchors +let rv_json = map_evidence_to_refval(&evidence).unwrap(); +let ta_json = map_evidence_to_trustanchor(&evidence.platform_claims, cpak_json).unwrap(); + +// The extracted values should be valid JSON +assert!(serde_json::from_str::(&rv_json).is_ok()); +assert!(serde_json::from_str::(&ta_json).is_ok()); +``` + +## 5. Implementation Plan + +### 5.1 Existing Tests + +Many of the tests defined in this plan are already implemented in the codebase, particularly in `src/token/evidence.rs`, `src/token/realm.rs`, and `src/token/platform.rs`. These should be reviewed and updated to ensure they align with this test plan. + +### 5.2 Additional Tests Needed + +The following tests should be added to complete the test coverage: + +1. More comprehensive malformed token tests +2. Reference value mismatch tests for both platform and realm +3. Specific tests for handling unknown reference values +4. Additional binding verification tests +5. More comprehensive end-to-end tests + +### 5.3 Test Data Organization + +Test data should be organized in the `testdata` directory with clear naming conventions: + +- `cca-token-*.cbor`: Complete token collections +- `platform-claims-*.cbor`: Platform-specific test vectors +- `realm-claims-*.cbor`: Realm-specific test vectors +- `ta-*.json`: Trust anchor store test data +- `rv-*.json`: Reference value store test data + +Each test file should have a corresponding `.diag` file with a human-readable representation of the binary CBOR data. + +### 5.4 Test Automation + +All tests should be automated as part of the crate's test suite, runnable with `cargo test`. Integration tests that require command-line interaction should be implemented as separate tests that can be run with a specific feature flag. \ No newline at end of file diff --git a/docs/reference_value_mismatch_tests.md b/docs/reference_value_mismatch_tests.md new file mode 100644 index 0000000..3bd98ac --- /dev/null +++ b/docs/reference_value_mismatch_tests.md @@ -0,0 +1,173 @@ +# Test Data for Reference Value Mismatches + +This file contains test data for testing reference value mismatches between CCA tokens and reference values. + +## Platform Implementation ID Mismatch + +A reference value with a different implementation ID than the one in the token. + +```json +{ + "platform": [ + { + "implementation-id": "FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE", + "sw-components": [ + { + "measurement-value": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "FF00000000000000000000000000000000000000000000000000000000000000", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "54686520717569636B2062726F776E20666F78206A756D7073206F766572203133206C617A7920646F67732E54686520717569636B2062726F776E20666F7820" + } + ] +} +``` + +## Platform SW Component Mismatch + +A reference value with different software component measurements than the ones in the token. + +```json +{ + "platform": [ + { + "implementation-id": "7F454C4602010100000000000000000003003E00010000005058000000000000", + "sw-components": [ + { + "measurement-value": "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "FF00000000000000000000000000000000000000000000000000000000000000", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "54686520717569636B2062726F776E20666F78206A756D7073206F766572203133206C617A7920646F67732E54686520717569636B2062726F776E20666F7820" + } + ] +} +``` + +## Realm Initial Measurement Mismatch + +A reference value with a different realm initial measurement than the one in the token. + +```json +{ + "platform": [ + { + "implementation-id": "7F454C4602010100000000000000000003003E00010000005058000000000000", + "sw-components": [ + { + "measurement-value": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "54686520717569636B2062726F776E20666F78206A756D7073206F766572203133206C617A7920646F67732E54686520717569636B2062726F776E20666F7820" + } + ] +} +``` + +## Realm Extensible Measurement Mismatch + +A reference value with different realm extensible measurements than the ones in the token. + +```json +{ + "platform": [ + { + "implementation-id": "7F454C4602010100000000000000000003003E00010000005058000000000000", + "sw-components": [ + { + "measurement-value": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "FF00000000000000000000000000000000000000000000000000000000000000", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "54686520717569636B2062726F776E20666F78206A756D7073206F766572203133206C617A7920646F67732E54686520717569636B2062726F776E20666F7820" + } + ] +} +``` + +## Personalization Value Mismatch + +A reference value with a different personalization value than the one in the token. + +```json +{ + "platform": [ + { + "implementation-id": "7F454C4602010100000000000000000003003E00010000005058000000000000", + "sw-components": [ + { + "measurement-value": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "FF00000000000000000000000000000000000000000000000000000000000000", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF" + } + ] +} +``` \ No newline at end of file diff --git a/src/token/evidence.rs b/src/token/evidence.rs index 5c82010..ee78f98 100644 --- a/src/token/evidence.rs +++ b/src/token/evidence.rs @@ -757,4 +757,124 @@ mod tests { serde_json::to_string_pretty(&evidence.realm_tvec).unwrap() ); } + + // Additional reference value mismatch tests + const TEST_RV_IMPL_ID_MISMATCH: &str = include_str!("../../testdata/rv-impl-id-mismatch.json"); + const TEST_RV_SWCOMP_MISMATCH: &str = include_str!("../../testdata/rv-swcomp-mismatch.json"); + const TEST_RV_RIM_MISMATCH: &str = include_str!("../../testdata/rv-rim-mismatch.json"); + const TEST_RV_REM_MISMATCH: &str = include_str!("../../testdata/rv-rem-mismatch.json"); + const TEST_RV_PERSO_MISMATCH: &str = include_str!("../../testdata/rv-perso-mismatch.json"); + const TEST_RV_EMPTY: &str = include_str!("../../testdata/rv-empty.json"); + + #[test] + fn appraise_platform_impl_id_mismatch() { + let mut rvs = MemoRefValueStore::new(); + rvs.load_json(TEST_RV_IMPL_ID_MISMATCH) + .expect("loading TEST_RV_IMPL_ID_MISMATCH"); + + let mut e = + Evidence::decode(TEST_CCA_TOKEN_1_OK.as_slice()).expect("decoding TEST_CCA_TOKEN_1_OK"); + + e.appraise(&rvs).expect("appraisal completed"); + + // The platform implementation ID is different, so platform should be NO_CLAIM + assert_eq!( + e.platform_tvec.instance_identity, + ear::claim::NO_CLAIM + ); + } + + #[test] + fn appraise_platform_swcomp_mismatch() { + let mut rvs = MemoRefValueStore::new(); + rvs.load_json(TEST_RV_SWCOMP_MISMATCH) + .expect("loading TEST_RV_SWCOMP_MISMATCH"); + + let mut e = + Evidence::decode(TEST_CCA_TOKEN_1_OK.as_slice()).expect("decoding TEST_CCA_TOKEN_1_OK"); + + e.appraise(&rvs).expect("appraisal completed"); + + // The SW component measurement is different, so platform should be NO_CLAIM + assert_eq!( + e.platform_tvec.instance_identity, + ear::claim::NO_CLAIM + ); + } + + #[test] + fn appraise_realm_rim_mismatch() { + let mut rvs = MemoRefValueStore::new(); + rvs.load_json(TEST_RV_RIM_MISMATCH) + .expect("loading TEST_RV_RIM_MISMATCH"); + + let mut e = + Evidence::decode(TEST_CCA_TOKEN_1_OK.as_slice()).expect("decoding TEST_CCA_TOKEN_1_OK"); + + e.appraise(&rvs).expect("appraisal completed"); + + // The realm initial measurement is different, so realm should be NO_CLAIM + assert_eq!( + e.realm_tvec.instance_identity, + ear::claim::NO_CLAIM + ); + } + + #[test] + fn appraise_realm_rem_mismatch() { + let mut rvs = MemoRefValueStore::new(); + rvs.load_json(TEST_RV_REM_MISMATCH) + .expect("loading TEST_RV_REM_MISMATCH"); + + let mut e = + Evidence::decode(TEST_CCA_TOKEN_1_OK.as_slice()).expect("decoding TEST_CCA_TOKEN_1_OK"); + + e.appraise(&rvs).expect("appraisal completed"); + + // The realm extensible measurement is different, so realm should be NO_CLAIM + assert_eq!( + e.realm_tvec.instance_identity, + ear::claim::NO_CLAIM + ); + } + + #[test] + fn appraise_realm_perso_mismatch() { + let mut rvs = MemoRefValueStore::new(); + rvs.load_json(TEST_RV_PERSO_MISMATCH) + .expect("loading TEST_RV_PERSO_MISMATCH"); + + let mut e = + Evidence::decode(TEST_CCA_TOKEN_1_OK.as_slice()).expect("decoding TEST_CCA_TOKEN_1_OK"); + + e.appraise(&rvs).expect("appraisal completed"); + + // The personalization value is different, so realm should be NO_CLAIM + assert_eq!( + e.realm_tvec.instance_identity, + ear::claim::NO_CLAIM + ); + } + + #[test] + fn appraise_empty_refvals() { + let mut rvs = MemoRefValueStore::new(); + rvs.load_json(TEST_RV_EMPTY) + .expect("loading TEST_RV_EMPTY"); + + let mut e = + Evidence::decode(TEST_CCA_TOKEN_1_OK.as_slice()).expect("decoding TEST_CCA_TOKEN_1_OK"); + + e.appraise(&rvs).expect("appraisal completed"); + + // No reference values found, so both should be NO_CLAIM + assert_eq!( + e.platform_tvec.instance_identity, + ear::claim::NO_CLAIM + ); + assert_eq!( + e.realm_tvec.instance_identity, + ear::claim::NO_CLAIM + ); + } } diff --git a/testdata/README.md b/testdata/README.md new file mode 100644 index 0000000..fc6c3a4 --- /dev/null +++ b/testdata/README.md @@ -0,0 +1,66 @@ +# Test Data Organization for rust-ccatoken + +This directory contains test data for the rust-ccatoken library. The files are organized as follows: + +## Token Collections + +Complete CCA token collections (containing both platform and realm tokens): + +- `cca-token-01.cbor`: Standard valid CCA token +- `cca-token-01.diag`: Human-readable diagnostic format of `cca-token-01.cbor` +- `cca-token-02.cbor`: Alternative valid CCA token format +- `cca-token-02.diag`: Human-readable diagnostic format of `cca-token-02.cbor` +- `cca-token-draft-ffm-00.cbor`: Draft FFM format token +- `bug-33-repro.cbor`: Token that reproduces bug #33 (correctly signed platform but incorrectly signed realm) + +## Platform and Realm Claims + +Individual platform and realm claims for testing specific components: + +- `platform-claims.cbor`: Platform claims CBOR data +- `platform-claims.diag`: Human-readable diagnostic format of `platform-claims.cbor` +- `realm-claims.cbor`: Realm claims CBOR data +- `realm-claims.diag`: Human-readable diagnostic format of `realm-claims.diag` + +## Malformed Claims + +Claims with specific issues for testing error handling: + +- `realm-claims-missing-challenge.cbor`: Realm claims with missing challenge field +- `realm-claims-missing-challenge.diag`: Human-readable format of the above +- `realm-claims+spurious-numeric-key.cbor`: Realm claims with additional unexpected numeric key +- `realm-claims+spurious-numeric-key.diag`: Human-readable format of the above +- `realm-claims+spurious-text-key.cbor`: Realm claims with additional unexpected text key +- `realm-claims+spurious-text-key.diag`: Human-readable format of the above + +## Trust Anchor Store Test Data + +JSON files containing trust anchors for verification testing: + +- `ta.json`: Standard trust anchor store +- `ta-02-ok.json`: Trust anchor store for `cca-token-02.cbor` with correct CPAK +- `ta-02-bad.json`: Trust anchor store for `cca-token-02.cbor` with incorrect CPAK +- `ta-tfa.json`: Trust anchor store for TFA testing + +## Reference Value Store Test Data + +JSON files containing reference values for appraisal testing: + +- `rv.json`: Standard reference value store with matching values +- `rv-impl-id-mismatch.json`: Reference values with mismatched implementation ID +- `rv-swcomp-mismatch.json`: Reference values with mismatched SW component measurement +- `rv-rim-mismatch.json`: Reference values with mismatched realm initial measurement +- `rv-rem-mismatch.json`: Reference values with mismatched realm extensible measurement +- `rv-perso-mismatch.json`: Reference values with mismatched personalization value +- `rv-empty.json`: Empty reference value store + +## Other Test Data + +- `cpak.json`: CPAK (Confidential Platform Attestation Key) for testing +- `impl-id.bin`: Implementation ID binary data +- `inst-id.bin`: Instance ID binary data +- `pkey.json`: Public key data for testing + +## Test Data Generation + +The `Makefile` in this directory can be used to generate or regenerate test data as needed. \ No newline at end of file diff --git a/testdata/rv-empty.json b/testdata/rv-empty.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/testdata/rv-empty.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/testdata/rv-impl-id-mismatch.json b/testdata/rv-impl-id-mismatch.json new file mode 100644 index 0000000..ee442ca --- /dev/null +++ b/testdata/rv-impl-id-mismatch.json @@ -0,0 +1,27 @@ +{ + "platform": [ + { + "implementation-id": "FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE", + "sw-components": [ + { + "measurement-value": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "FF00000000000000000000000000000000000000000000000000000000000000", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "54686520717569636B2062726F776E20666F78206A756D7073206F766572203133206C617A7920646F67732E54686520717569636B2062726F776E20666F7820" + } + ] +} \ No newline at end of file diff --git a/testdata/rv-perso-mismatch.json b/testdata/rv-perso-mismatch.json new file mode 100644 index 0000000..7989638 --- /dev/null +++ b/testdata/rv-perso-mismatch.json @@ -0,0 +1,27 @@ +{ + "platform": [ + { + "implementation-id": "7F454C4602010100000000000000000003003E00010000005058000000000000", + "sw-components": [ + { + "measurement-value": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "FF00000000000000000000000000000000000000000000000000000000000000", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF" + } + ] +} \ No newline at end of file diff --git a/testdata/rv-rem-mismatch.json b/testdata/rv-rem-mismatch.json new file mode 100644 index 0000000..6c629d4 --- /dev/null +++ b/testdata/rv-rem-mismatch.json @@ -0,0 +1,27 @@ +{ + "platform": [ + { + "implementation-id": "7F454C4602010100000000000000000003003E00010000005058000000000000", + "sw-components": [ + { + "measurement-value": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "FF00000000000000000000000000000000000000000000000000000000000000", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "54686520717569636B2062726F776E20666F78206A756D7073206F766572203133206C617A7920646F67732E54686520717569636B2062726F776E20666F7820" + } + ] +} \ No newline at end of file diff --git a/testdata/rv-rim-mismatch.json b/testdata/rv-rim-mismatch.json new file mode 100644 index 0000000..5afe334 --- /dev/null +++ b/testdata/rv-rim-mismatch.json @@ -0,0 +1,27 @@ +{ + "platform": [ + { + "implementation-id": "7F454C4602010100000000000000000003003E00010000005058000000000000", + "sw-components": [ + { + "measurement-value": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "54686520717569636B2062726F776E20666F78206A756D7073206F766572203133206C617A7920646F67732E54686520717569636B2062726F776E20666F7820" + } + ] +} \ No newline at end of file diff --git a/testdata/rv-swcomp-mismatch.json b/testdata/rv-swcomp-mismatch.json new file mode 100644 index 0000000..81aea37 --- /dev/null +++ b/testdata/rv-swcomp-mismatch.json @@ -0,0 +1,27 @@ +{ + "platform": [ + { + "implementation-id": "7F454C4602010100000000000000000003003E00010000005058000000000000", + "sw-components": [ + { + "measurement-value": "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", + "signer-id": "07060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "platform-configuration": "0107060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918" + } + ], + "realm": [ + { + "initial-measurement": "FF00000000000000000000000000000000000000000000000000000000000000", + "rak-hash-algorithm": "sha-256", + "extensible-measurements": [ + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + ], + "personalization-value": "54686520717569636B2062726F776E20666F78206A756D7073206F766572203133206C617A7920646F67732E54686520717569636B2062726F776E20666F7820" + } + ] +} \ No newline at end of file