├── nv-attestation-sdk-cpp ├── examples │ ├── attest │ │ └── CMakeLists.txt │ ├── custom-logger │ │ ├── CMakeLists.txt │ │ └── main.c │ ├── attest-minimal │ │ ├── CMakeLists.txt │ │ └── main.c │ ├── collect-gpu-evidence │ │ └── CMakeLists.txt │ ├── parallel-verification │ │ └── CMakeLists.txt │ └── CMakeLists.txt ├── .gitignore ├── test.env ├── unit-tests │ ├── testdata │ │ ├── spdm_req_parsed_output.json │ │ ├── switch_spdm_req_parsed_output.json │ │ ├── trusted_certs │ │ │ └── rim_root.crt │ │ ├── incorrect_rim_root.crt │ │ ├── sample_attestation_data │ │ │ ├── switch_decoded.json │ │ │ ├── hopperClaimsv3_decoded.json │ │ │ ├── switch_detached_eat.json │ │ │ ├── hopperClaimsv3_detached_eat.json │ │ │ └── switch │ │ │ │ ├── switchAttestationReport.txt │ │ │ │ └── switchAttestationReportInvalidSignature.txt │ │ ├── switchAttestationReport.txt │ │ └── hopperCertChain.txt │ ├── main.cpp │ ├── include │ │ ├── spdm_test_utils.h │ │ └── environment.h │ ├── error_test.cpp │ ├── rego_engine │ │ └── regorus_rego_engine_test.cpp │ ├── nv_http_test.cpp │ ├── switch_test_utils.cpp │ ├── CMakeLists.txt │ └── test_utils.cpp ├── cmake │ ├── Config.cmake.in │ ├── FindLibXml2.cmake │ └── Findxmlsec.cmake ├── scripts │ ├── generate_docs.sh │ ├── run-examples.sh │ └── lint.sh ├── src │ ├── trusted_certs │ │ └── rim_root.crt │ ├── utils.cpp │ ├── error.cpp │ ├── internal │ │ ├── certs.h │ │ ├── debug.hpp │ │ └── rego_engine │ │ │ ├── rego_engine.h │ │ │ └── regorus.hpp │ ├── rego_engine │ │ └── regorus_rego_engine.cpp │ ├── claims_evaluator.cpp │ ├── spdm │ │ └── spdm_req.cpp │ └── nv_cache.cpp ├── include │ └── nv_attestation │ │ ├── init.h │ │ ├── gpu │ │ ├── nvml_client.h │ │ └── claims.h │ │ ├── switch │ │ ├── nscq_client.h │ │ ├── claims.h │ │ └── verify.h │ │ ├── nv_jwt.h │ │ ├── spdm │ │ ├── spdm_req.hpp │ │ ├── spdm_opaque_data_parser.hpp │ │ ├── utils.h │ │ └── spdm_measurement_records.hpp │ │ ├── verify.h │ │ ├── nv_cache.h │ │ ├── claims_evaluator.h │ │ └── attestation.h ├── integration-tests │ ├── main.cpp │ ├── CMakeLists.txt │ ├── gpu_evidence_test.cpp │ └── switch_evidence_test.cpp └── CPackConfig.cmake.in ├── .gitignore ├── common-test-data ├── relying_party_policy.rego └── switch_relying_party_policy.rego ├── nv-attestation-cli ├── config.toml ├── src │ ├── version_config.h.in │ ├── utils.h │ ├── version.cpp │ ├── nvattest_options.h │ ├── version.h │ ├── collect_evidence.h │ ├── main.cpp │ ├── utils.cpp │ ├── attest.h │ └── nvattest_types.h ├── tests │ ├── main.cpp │ ├── CMakeLists.txt │ ├── test_utils.h │ ├── environment.h │ └── collect_evidence_tests.cpp └── CMakeLists.txt ├── SECURITY.md ├── CODE_OF_CONDUCT.md └── README.md /nv-attestation-sdk-cpp/examples/attest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(attest 2 | main.c 3 | ) 4 | 5 | target_link_libraries(attest 6 | nvat 7 | ) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | */env/* 2 | */target/* 3 | .vscode 4 | .idea 5 | .DS_Store 6 | */build/* 7 | *_build* 8 | *_repo* 9 | *.pyc 10 | build_docs/ 11 | build/ -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/examples/custom-logger/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(custom-logger 2 | main.c 3 | ) 4 | 5 | target_link_libraries(custom-logger 6 | nvat 7 | ) -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/examples/attest-minimal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(attest-minimal 2 | main.c 3 | ) 4 | 5 | target_link_libraries(attest-minimal 6 | nvat 7 | ) -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/examples/collect-gpu-evidence/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(collect-gpu-evidence 2 | main.c 3 | ) 4 | 5 | target_link_libraries(collect-gpu-evidence 6 | nvat 7 | ) -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/examples/parallel-verification/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(parallel-verification 2 | main.c 3 | ) 4 | 5 | target_link_libraries(parallel-verification 6 | nvat 7 | ) -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | *.code-workspace 3 | build/ 4 | .cache/ 5 | .cmake/ 6 | CMakeFiles/ 7 | CMakeUserPresets.json 8 | CMakePresets.json 9 | CMakeCache.txt 10 | docs/ 11 | out/ -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/test.env: -------------------------------------------------------------------------------- 1 | NVAT_RIM_SERVICE_BASE_URL?=https://rim.attestation.nvidia.com 2 | NVAT_OCSP_BASE_URL?=https://ocsp.ndis.nvidia.com 3 | NVAT_NRAS_BASE_URL?=https://nras.attestation.nvidia.com 4 | NVAT_C_SDK_TEST_SERVICE_KEY?= 5 | 6 | -------------------------------------------------------------------------------- /common-test-data/relying_party_policy.rego: -------------------------------------------------------------------------------- 1 | package policy 2 | import future.keywords.every 3 | 4 | default nv_match := false 5 | nv_match { 6 | every result in input { 7 | result["x-nvidia-device-type"] == "gpu" 8 | result.secboot 9 | result.dbgstat == "disabled" 10 | } 11 | } -------------------------------------------------------------------------------- /common-test-data/switch_relying_party_policy.rego: -------------------------------------------------------------------------------- 1 | package policy 2 | import future.keywords.every 3 | 4 | default nv_match := false 5 | nv_match { 6 | every result in input { 7 | result["x-nvidia-device-type"] == "nvswitch" 8 | result.secboot 9 | result.dbgstat == "disabled" 10 | } 11 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/spdm_req_parsed_output.json: -------------------------------------------------------------------------------- 1 | { 2 | "SPDMVersion": "0x11", 3 | "RequestResponseCode": "0xe0", 4 | "Param1": "0x01", 5 | "Param2": "0xff", 6 | "Nonce": "0x931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb", 7 | "SlotIDParam": "0x00" 8 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/switch_spdm_req_parsed_output.json: -------------------------------------------------------------------------------- 1 | { 2 | "SPDMVersion": "0x11", 3 | "RequestResponseCode": "0xe0", 4 | "Param1": "0x01", 5 | "Param2": "0xff", 6 | "Nonce": "0x931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb", 7 | "SlotIDParam": "0x00" 8 | } -------------------------------------------------------------------------------- /nv-attestation-cli/config.toml: -------------------------------------------------------------------------------- 1 | # Each section corresponds to a subcommand. The [default] section 2 | # holds global options and constants that apply to all subcommands, 3 | # or are used as application-wide configuration values. 4 | 5 | ## Display version information 6 | [version] 7 | 8 | [attest] 9 | device = "gpu" 10 | verifier = "local" 11 | gpu-evidence = "" 12 | switch-evidence = "" 13 | relying-party-policy = "" -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/cmake/Config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include(CMakeFindDependencyMacro) 4 | 5 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/Modules/") 6 | 7 | find_dependency(CURL REQUIRED) 8 | find_dependency(LibXml2 REQUIRED) 9 | find_dependency(OpenSSL REQUIRED) 10 | find_dependency(spdlog REQUIRED) 11 | find_dependency(xmlsec REQUIRED) 12 | 13 | include("${CMAKE_CURRENT_LIST_DIR}/nvatTargets.cmake") 14 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/scripts/generate_docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | readonly SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 6 | readonly PROJECT_DIR="$( cd "$SCRIPT_DIR/.." && pwd )" 7 | 8 | echo "--- Generating Doxygen Documentation ---" 9 | cd "$PROJECT_DIR" 10 | doxygen "Doxyfile" 11 | 12 | echo "--- Documentation Complete ---" 13 | echo "Find documentation site at '$PROJECT_DIR/docs/html/index.html'" -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Check if we're being built as a subdirectory 2 | if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 3 | # Standalone build - find installed SDK 4 | cmake_minimum_required(VERSION 3.11) 5 | project(nv-attestation-examples) 6 | 7 | set(CMAKE_CXX_STANDARD 14) 8 | 9 | find_package(nvat REQUIRED) 10 | # Set output directory for all example executables 11 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) 12 | endif() 13 | 14 | 15 | add_subdirectory(attest-minimal) 16 | add_subdirectory(attest) 17 | add_subdirectory(collect-gpu-evidence) 18 | add_subdirectory(custom-logger) 19 | add_subdirectory(parallel-verification) 20 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/trusted_certs/rim_root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICKTCCAbCgAwIBAgIQRdrjoA5QN73fh1N17LXicDAKBggqhkjOPQQDAzBFMQsw 3 | CQYDVQQGEwJVUzEPMA0GA1UECgwGTlZJRElBMSUwIwYDVQQDDBxOVklESUEgQ29S 4 | SU0gc2lnbmluZyBSb290IENBMCAXDTIzMDMxNjE1MzczNFoYDzIwNTMwMzA4MTUz 5 | NzM0WjBFMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGTlZJRElBMSUwIwYDVQQDDBxO 6 | VklESUEgQ29SSU0gc2lnbmluZyBSb290IENBMHYwEAYHKoZIzj0CAQYFK4EEACID 7 | YgAEuECyi9vNM+Iw2lfUzyBldHAwaC1HF7TCgp12QcEyUTm3Tagxwr48d55+K2VI 8 | lWYIDk7NlAIQdcV/Ff7euGLI+Qauj93HsSI4WX298PpW54RTgz9tC+Q684caR/BX 9 | WEeZo2MwYTAdBgNVHQ4EFgQUpaXrOPK4ZDAk08DBskn594zeZjAwHwYDVR0jBBgw 10 | FoAUpaXrOPK4ZDAk08DBskn594zeZjAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B 11 | Af8EBAMCAQYwCgYIKoZIzj0EAwMDZwAwZAIwHGDyscDP6ihHqRvZlI3eqZ4YkvjE 12 | 1duaN84tAHRVgxVMvNrp5Tnom3idHYGW/dskAjATvjIx6VzHm/4e2GiZAyZEIUBD 13 | OKPzp5ei/A0iUZpdvngenDwV8Qa/wGdiTmJ7Bp4= 14 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/trusted_certs/rim_root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICKTCCAbCgAwIBAgIQRdrjoA5QN73fh1N17LXicDAKBggqhkjOPQQDAzBFMQsw 3 | CQYDVQQGEwJVUzEPMA0GA1UECgwGTlZJRElBMSUwIwYDVQQDDBxOVklESUEgQ29S 4 | SU0gc2lnbmluZyBSb290IENBMCAXDTIzMDMxNjE1MzczNFoYDzIwNTMwMzA4MTUz 5 | NzM0WjBFMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGTlZJRElBMSUwIwYDVQQDDBxO 6 | VklESUEgQ29SSU0gc2lnbmluZyBSb290IENBMHYwEAYHKoZIzj0CAQYFK4EEACID 7 | YgAEuECyi9vNM+Iw2lfUzyBldHAwaC1HF7TCgp12QcEyUTm3Tagxwr48d55+K2VI 8 | lWYIDk7NlAIQdcV/Ff7euGLI+Qauj93HsSI4WX298PpW54RTgz9tC+Q684caR/BX 9 | WEeZo2MwYTAdBgNVHQ4EFgQUpaXrOPK4ZDAk08DBskn594zeZjAwHwYDVR0jBBgw 10 | FoAUpaXrOPK4ZDAk08DBskn594zeZjAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B 11 | Af8EBAMCAQYwCgYIKoZIzj0EAwMDZwAwZAIwHGDyscDP6ihHqRvZlI3eqZ4YkvjE 12 | 1duaN84tAHRVgxVMvNrp5Tnom3idHYGW/dskAjATvjIx6VzHm/4e2GiZAyZEIUBD 13 | OKPzp5ei/A0iUZpdvngenDwV8Qa/wGdiTmJ7Bp4= 14 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Security 2 | 3 | NVIDIA is dedicated to the security and trust of our software products and services, including all source code repositories managed through our organization. 4 | 5 | If you need to report a security issue, please use the appropriate contact points outlined below. **Please do not report security vulnerabilities through GitHub.** 6 | 7 | ## Reporting Potential Security Vulnerability in an NVIDIA Product 8 | 9 | To report a potential security vulnerability in any NVIDIA product: 10 | - Web: [Security Vulnerability Submission Form](https://www.nvidia.com/object/submit-security-vulnerability.html) 11 | - E-Mail: psirt@nvidia.com 12 | - We encourage you to use the following PGP key for secure email communication: [NVIDIA public PGP Key for communication](https://www.nvidia.com/en-us/security/pgp-key) 13 | - Please include the following information: 14 | - Product/Driver name and version/branch that contains the vulnerability 15 | -------------------------------------------------------------------------------- /nv-attestation-cli/src/version_config.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #define NVATTEST_VERSION_STRING "@PROJECT_VERSION@" 21 | #define NVATTEST_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@" 22 | #define NVATTEST_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@" 23 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/incorrect_rim_root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICpTCCAiygAwIBAgIUQ6Y8rzOIc5EftD/YmHaQtNLo3dMwCgYIKoZIzj0EAwMw 3 | YzE3MDUGA1UEAwwuTlZJRElBIFJlZmVyZW5jZSBWYWx1ZSBMMyBHSDEwMCAwMDEg 4 | RGVidWcgT25seTEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0aW9uMQswCQYDVQQG 5 | EwJVUzAeFw0yNTAyMDEwNDUzNDRaFw0yNzAyMDEwNDUzNDRaMGkxCzAJBgNVBAYT 6 | AlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGzAZBgNVBAoM 7 | Ek5WSURJQSBDb3Jwb3JhdGlvbjEaMBgGA1UEAwwRSENDIFJJTSBMNCBTaWduZXIw 8 | djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQq1rOTwJlDcNf21AwDjew7RpnNPCw3xyYk 9 | u4PFljwJ+zcshuIsizEU8SPDGh7vCX02O0VLUSrPX6SAJolBS2FlPvsyYJbWiirA 10 | w6JdOCkAGqPivrURuKlryyt/kytPYOOjgZowgZcwHQYDVR0OBBYEFKffkV78is0M 11 | auoedMno73ktfn7xMB8GA1UdIwQYMBaAFBzf8PI3Yf0rugwBbP4+bTnTgWKfMAwG 12 | A1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMDcGCCsGAQUFBwEBBCswKTAnBggr 13 | BgEFBQcwAYYbaHR0cDovL29jc3AubmRpcy5udmlkaWEuY29tMAoGCCqGSM49BAMD 14 | A2cAMGQCMHNSzrSgyto4ufL5WCbc7fOdITFUI/STz+YjRLJn4Tk8cZMQaGKiyAD2 15 | FBJW2ErSGAIwcJuXV9r65+pJJHb2OCemylk9QAvPC750Cj/UJjp9Qa6mlfuOZgta 16 | F0S5R+yBSf+N 17 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /nv-attestation-cli/tests/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include "environment.h" 20 | 21 | Environment* g_cli_env = nullptr; 22 | 23 | int main(int argc, char **argv) { 24 | ::testing::InitGoogleTest(&argc, argv); 25 | g_cli_env = static_cast(::testing::AddGlobalTestEnvironment(new Environment)); 26 | return RUN_ALL_TESTS(); 27 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include "environment.h" 20 | 21 | Environment* g_env = nullptr; 22 | 23 | int main(int argc, char **argv) { 24 | ::testing::InitGoogleTest(&argc, argv); 25 | g_env = static_cast(::testing::AddGlobalTestEnvironment(new Environment)); 26 | return RUN_ALL_TESTS(); 27 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/init.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "log.h" 21 | 22 | namespace nvattestation { 23 | struct SdkOptions { 24 | std::shared_ptr logger; 25 | }; 26 | 27 | 28 | // If this function is not called, using the SDK is undefined behavior. 29 | // Calling this function more than once is undefined behavior. 30 | Error init(const std::shared_ptr& options); 31 | void shutdown(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /nv-attestation-cli/src/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "CLI/CLI.hpp" 21 | #include "nvattest_options.h" 22 | 23 | namespace nvattest { 24 | void add_evidence_collection_options(CLI::App* app, EvidenceCollectionOptions& options); 25 | void add_evidence_policy_options(CLI::App* app, EvidencePolicyOptions& options); 26 | void add_evidence_verification_options(CLI::App* app, EvidenceVerificationOptions& options); 27 | void add_common_options(CLI::App& app, CommonOptions& options); 28 | } 29 | -------------------------------------------------------------------------------- /nv-attestation-cli/src/version.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "version.h" 19 | #include "version_config.h" 20 | #include "spdlog/spdlog.h" 21 | 22 | namespace nvattest { 23 | 24 | CLI::App* create_version_subcommand(CLI::App& app) { 25 | return app.add_subcommand("version", "Display version information"); 26 | } 27 | 28 | int handle_version_subcommand() { 29 | SPDLOG_INFO("nvattest {} ({}/{})", NVATTEST_VERSION_STRING, NVATTEST_SYSTEM_NAME, NVATTEST_SYSTEM_PROCESSOR); 30 | return 0; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/gpu/nvml_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "nv_attestation/error.h" 25 | #include "nv_attestation/gpu/evidence.h" 26 | 27 | namespace nvattestation { 28 | 29 | extern bool g_nvml_initialized; 30 | 31 | Error init_nvml(); 32 | void shutdown_nvml(); 33 | Error get_driver_version(std::string& out_driver_version); 34 | Error collect_evidence_nvml(const std::vector& nonce_input, std::vector>& out_evidence); 35 | 36 | } // namespace nvattestation 37 | 38 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "nv_attestation/utils.h" 2 | #include "nv_attestation/log.h" 3 | #include "nv_attestation/nv_types.h" 4 | #include "nv_attestation/error.h" 5 | 6 | #include 7 | 8 | namespace nvattestation { 9 | Error compute_sha256_hex(const std::string& data, std::string& out_hex) { 10 | nv_unique_ptr ctx(EVP_MD_CTX_new()); 11 | if (!ctx) { 12 | LOG_ERROR("EVP_MD_CTX_new failed: " << get_openssl_error()); 13 | return Error::InternalError; 14 | } 15 | if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr) != 1) { 16 | LOG_ERROR("EVP_DigestInit_ex failed: " << get_openssl_error()); 17 | return Error::InternalError; 18 | } 19 | if (EVP_DigestUpdate(ctx.get(), data.data(), data.size()) != 1) { 20 | LOG_ERROR("EVP_DigestUpdate failed: " << get_openssl_error()); 21 | return Error::InternalError; 22 | } 23 | unsigned char digest[EVP_MAX_MD_SIZE]; 24 | unsigned int digest_len = 0; 25 | if (EVP_DigestFinal_ex(ctx.get(), digest, &digest_len) != 1) { 26 | LOG_ERROR("EVP_DigestFinal_ex failed: " << get_openssl_error()); 27 | return Error::InternalError; 28 | } 29 | std::vector digest_vec(digest, digest + digest_len); 30 | out_hex = to_hex_string(digest_vec); 31 | return Error::Ok; 32 | } 33 | 34 | } // namespace nvattestation -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/include/spdm_test_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | #include 20 | 21 | #include "gtest/gtest.h" 22 | #include "nlohmann/json.hpp" 23 | #include "nv_attestation/spdm/spdm_resp.hpp" 24 | #include "nv_attestation/utils.h" 25 | 26 | namespace nvattestation { 27 | 28 | void parse_and_verify_spdm_response( 29 | const nvattestation::SpdmMeasurementResponseMessage11& msg, 30 | const nlohmann::json& expected_values_json); 31 | 32 | void parse_and_verify_measurement_records( 33 | const nvattestation::SpdmMeasurementResponseMessage11& msg, 34 | const nlohmann::json& expected_values_json); 35 | 36 | } // namespace nvattestation -------------------------------------------------------------------------------- /nv-attestation-cli/src/nvattest_options.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | namespace nvattest { 23 | 24 | struct EvidenceCollectionOptions { 25 | std::string nonce; 26 | std::string device; 27 | }; 28 | 29 | struct EvidencePolicyOptions { 30 | }; 31 | 32 | struct EvidenceVerificationOptions { 33 | std::string verifier; 34 | std::string relying_party_policy; 35 | std::string rim_url; 36 | std::string ocsp_url; 37 | std::string nras_url; 38 | std::string gpu_evidence; 39 | std::string switch_evidence; 40 | std::string service_key; 41 | }; 42 | 43 | struct CommonOptions { 44 | std::string log_level; 45 | }; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /nv-attestation-cli/src/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | #include 20 | #include 21 | #include "CLI/CLI.hpp" 22 | 23 | namespace nvattest { 24 | /** 25 | * @brief Creates and adds the 'version' subcommand to the main CLI application. 26 | * 27 | * @param app The main CLI::App object to which the subcommand will be added. 28 | * @return A pointer to the created CLI::App subcommand object. 29 | */ 30 | CLI::App* create_version_subcommand(CLI::App& app); 31 | 32 | /** 33 | * @brief Handles the logic when the 'version' subcommand is invoked. 34 | * 35 | * @return Exit code for the subcommand handler (0 for success). 36 | */ 37 | int handle_version_subcommand(); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/error_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | //stdlibs 19 | #include 20 | 21 | //third party 22 | #include "gtest/gtest.h" 23 | #include "gmock/gmock.h" 24 | 25 | //this sdk 26 | #include "nv_attestation/error.h" 27 | 28 | using namespace nvattestation; 29 | 30 | class ErrorTest : public ::testing::Test { 31 | 32 | }; 33 | 34 | TEST_F(ErrorTest, ErrorEnumValuesAreUnique) { 35 | std::set values; 36 | for (Error e : ErrorValues) { 37 | int val = static_cast(e); 38 | EXPECT_TRUE(values.insert(val).second) << "Duplicate enum value: " << val; 39 | } 40 | } 41 | 42 | TEST_F(ErrorTest, EnumValuesHaveAToString) { 43 | for (Error e : ErrorValues) { 44 | std::string message = nvattestation::to_string(e); 45 | EXPECT_NE(message, "Undefined"); 46 | } 47 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/cmake/FindLibXml2.cmake: -------------------------------------------------------------------------------- 1 | # Prevent infinite recursion 2 | if(DEFINED _FIND_LIBXML2_GUARD) 3 | return() 4 | endif() 5 | set(_FIND_LIBXML2_GUARD ON) 6 | 7 | list(REMOVE_ITEM CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") 8 | find_package(LibXml2) 9 | 10 | if (NOT LibXml2_FOUND) 11 | find_package(PkgConfig) 12 | 13 | if(PKG_CONFIG_FOUND) 14 | pkg_check_modules(PC_LibXml2 QUIET libxml-2.0) 15 | endif() 16 | 17 | if(CMAKE_VERSION VERSION_LESS 3.12.0) 18 | list(APPEND LibXml2_ROOT "$ENV{LibXml2_ROOT}") 19 | endif() 20 | 21 | list(APPEND LibXml2_ROOT "${LibXml2_ROOT_DIR}" "$ENV{LibXml2_ROOT_DIR}") 22 | list(REMOVE_ITEM LibXml2_ROOT "") 23 | list(REMOVE_DUPLICATES LibXml2_ROOT) 24 | 25 | find_path(LibXml2_INCLUDE_DIR 26 | NAMES libxml/parser.h 27 | PATHS ${LibXml2_ROOT} 28 | HINTS ${PC_LibXml2_INCLUDE_DIRS} 29 | ) 30 | 31 | find_library(LibXml2_LIBRARY 32 | NAMES xml2 33 | PATHS ${LibXml2_ROOT} 34 | HINTS ${PC_LibXml2_LIBRARY_DIRS} 35 | ) 36 | 37 | include(FindPackageHandleStandardArgs) 38 | find_package_handle_standard_args(LibXml2 39 | REQUIRED_VARS LibXml2_LIBRARY LibXml2_INCLUDE_DIR 40 | ) 41 | endif() 42 | 43 | if(LibXml2_FOUND AND NOT TARGET LibXml2::LibXml2) 44 | add_library(LibXml2::LibXml2 UNKNOWN IMPORTED) 45 | set_target_properties(LibXml2::LibXml2 PROPERTIES 46 | IMPORTED_LOCATION "${LibXml2_LIBRARY}" 47 | INTERFACE_INCLUDE_DIRECTORIES "${LibXml2_INCLUDE_DIR}" 48 | ) 49 | endif() 50 | 51 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") 52 | 53 | # Clean up guard variable 54 | unset(_FIND_LIBXML2_GUARD) 55 | -------------------------------------------------------------------------------- /nv-attestation-cli/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(nv-attestation-cli-tests) 3 | 4 | find_package(GTest REQUIRED) 5 | 6 | option(SANITIZER "Select a sanitizer" OFF) 7 | 8 | add_executable(nv-attestation-cli-tests 9 | main.cpp 10 | attest_tests.cpp 11 | collect_evidence_tests.cpp 12 | test_utils.h 13 | environment.h 14 | ${nvattest_SOURCE_DIR}/src/attest.cpp 15 | ${nvattest_SOURCE_DIR}/src/collect_evidence.cpp 16 | ${nvattest_SOURCE_DIR}/src/utils.cpp 17 | ) 18 | 19 | target_include_directories(nv-attestation-cli-tests PRIVATE 20 | ${nvattest_SOURCE_DIR}/src 21 | ) 22 | 23 | if (SANITIZER) 24 | target_compile_options(nv-attestation-cli-tests PRIVATE -fsanitize=${SANITIZER} -fno-sanitize-recover=all) 25 | target_link_options(nv-attestation-cli-tests PRIVATE -fsanitize=${SANITIZER} -fno-sanitize-recover=all) 26 | endif() 27 | target_compile_options(nv-attestation-cli-tests PRIVATE -Wno-unused -Wno-c++17-attribute-extensions) 28 | 29 | find_package(spdlog REQUIRED) 30 | 31 | target_link_libraries(nv-attestation-cli-tests PRIVATE 32 | GTest::gtest 33 | GTest::gmock 34 | nlohmann_json::nlohmann_json 35 | spdlog::spdlog 36 | CLI11::CLI11 37 | ) 38 | 39 | if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 40 | # CMake file is being run on its own (standalone) 41 | find_package(nvat REQUIRED) 42 | target_link_libraries(nv-attestation-cli-tests PRIVATE nvat::nvat) 43 | else() 44 | # CMake file is being invoked as part of subdirectory from another CMake file 45 | target_link_libraries(nv-attestation-cli-tests PRIVATE nvat) 46 | endif() 47 | 48 | include(GoogleTest) 49 | gtest_discover_tests(nv-attestation-cli-tests PROPERTIES LABELS "cli") -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/sample_attestation_data/switch_decoded.json: -------------------------------------------------------------------------------- 1 | { 2 | "SWITCH-0": { 3 | "x-nvidia-switch-bios-rim-fetched": true, 4 | "x-nvidia-switch-bios-rim-signature-verified": true, 5 | "x-nvidia-switch-attestation-report-cert-chain-fwid-match": true, 6 | "x-nvidia-switch-attestation-report-signature-verified": true, 7 | "x-nvidia-switch-bios-rim-version-match": true, 8 | "x-nvidia-switch-attestation-report-parsed": true, 9 | "iss": "https://nras.attestation-stg.nvidia.com", 10 | "eat_nonce": "931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb", 11 | "x-nvidia-switch-attestation-report-nonce-match": true, 12 | "x-nvidia-switch-attestation-report-cert-chain": { 13 | "x-nvidia-cert-status": "valid", 14 | "x-nvidia-cert-ocsp-status": "good", 15 | "x-nvidia-cert-expiration-date": "9999-12-31T23:59:59Z", 16 | "x-nvidia-cert-revocation-reason": null 17 | }, 18 | "exp": 1751158660, 19 | "iat": 1751155060, 20 | "ueid": "694931143880983876767046803400974855445978836716", 21 | "jti": "1012d8b1-b52d-4870-9b9e-6ef6b05ba7f2", 22 | "x-nvidia-switch-arch-check": true, 23 | "secboot": true, 24 | "x-nvidia-switch-bios-rim-schema-validated": true, 25 | "x-nvidia-switch-bios-rim-cert-chain": { 26 | "x-nvidia-cert-status": "valid", 27 | "x-nvidia-cert-ocsp-status": "good", 28 | "x-nvidia-cert-expiration-date": "2026-05-20T17:59:06Z", 29 | "x-nvidia-cert-revocation-reason": null 30 | }, 31 | "x-nvidia-attestation-warning": null, 32 | "nbf": 1751155060, 33 | "hwmodel": "LS_10 A01 FSP BROM", 34 | "dbgstat": "disabled", 35 | "x-nvidia-switch-bios-rim-measurements-available": true, 36 | "oemid": null, 37 | "measres": "success", 38 | "x-nvidia-switch-bios-version": "96.10.55.00.01" 39 | } 40 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/switch/nscq_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "nv_attestation/error.h" 23 | #include "nv_attestation/switch/evidence.h" 24 | 25 | namespace nvattestation { 26 | 27 | constexpr unsigned int NSCQ_ATTESTATION_REPORT_NONCE_SIZE = 0x20; 28 | 29 | extern bool g_nscq_initialized; 30 | 31 | enum class SwitchTnvlMode { 32 | Unknown = -1, 33 | Disabled = 0, 34 | Enabled = 1, 35 | Failure = 2, 36 | Locked = 3 37 | }; 38 | 39 | Error init_nscq(); 40 | void shutdown_nscq(); 41 | 42 | Error collect_evidence_nscq(const std::vector& nonce_input, std::vector>& out_evidence); 43 | 44 | Error get_all_switch_uuid(std::vector& out_uuids); 45 | Error get_switch_tnvl_status(const std::string& uuid, SwitchTnvlMode& out_tnvl_mode); 46 | Error get_attestation_cert_chain(const std::string& uuid, std::string& out_cert_chain); 47 | Error get_attestation_report(const std::string& uuid, const std::vector& nonce_input, std::vector& out_attestation_report); 48 | Error get_switch_architecture(SwitchArchitecture& out_arch); 49 | 50 | } // namespace nvattestation -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/scripts/run-examples.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to run all example executables and verify they execute without errors 3 | # Usage: ./run-examples.sh 4 | 5 | set -euo pipefail 6 | 7 | if [ $# -ne 1 ]; then 8 | echo "Usage: $0 " 9 | exit 1 10 | fi 11 | 12 | EXAMPLES_BUILD_DIR="$1" 13 | 14 | if [ ! -d "$EXAMPLES_BUILD_DIR" ]; then 15 | echo "Error: Directory '$EXAMPLES_BUILD_DIR' does not exist" 16 | exit 1 17 | fi 18 | 19 | # Find all executable files in the examples build directory 20 | mapfile -t EXAMPLE_PATHS < <(find "$EXAMPLES_BUILD_DIR" -type f -executable | sort) 21 | 22 | if [ ${#EXAMPLE_PATHS[@]} -eq 0 ]; then 23 | echo "Error: No executable files found in '$EXAMPLES_BUILD_DIR'" 24 | exit 1 25 | fi 26 | 27 | echo "Running examples from: $EXAMPLES_BUILD_DIR" 28 | echo "Found ${#EXAMPLE_PATHS[@]} executable(s)" 29 | echo "========================================" 30 | echo "" 31 | 32 | FAILED_EXAMPLES=() 33 | SUCCESS_COUNT=0 34 | TOTAL_COUNT=${#EXAMPLE_PATHS[@]} 35 | 36 | for EXAMPLE_PATH in "${EXAMPLE_PATHS[@]}"; do 37 | EXAMPLE_NAME=$(basename "$EXAMPLE_PATH") 38 | 39 | echo "Running $EXAMPLE_NAME..." 40 | 41 | if "$EXAMPLE_PATH"; then 42 | echo "$EXAMPLE_NAME completed successfully" 43 | SUCCESS_COUNT=$((SUCCESS_COUNT + 1)) 44 | else 45 | EXIT_CODE=$? 46 | echo "$EXAMPLE_NAME failed with exit code $EXIT_CODE" 47 | FAILED_EXAMPLES+=("$EXAMPLE_NAME") 48 | fi 49 | echo "" 50 | done 51 | 52 | echo "========================================" 53 | echo "Results: $SUCCESS_COUNT/$TOTAL_COUNT examples passed" 54 | 55 | if [ ${#FAILED_EXAMPLES[@]} -gt 0 ]; then 56 | echo "" 57 | echo "Failed examples:" 58 | for failed in "${FAILED_EXAMPLES[@]}"; do 59 | echo " - $failed" 60 | done 61 | exit 1 62 | fi 63 | 64 | echo "All examples ran successfully!" 65 | exit 0 66 | 67 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/integration-tests/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include "nv_attestation/init.h" 20 | #include "nv_attestation/error.h" 21 | 22 | using namespace nvattestation; 23 | 24 | // this is currently duplicated in unit-tests/main.cpp 25 | // todo(p3): if this does not change signficantly between unit-tests and integration-tests, 26 | // move it to a common test folder (that folder would have to included in the 27 | // target include directories for both unit-tests and integration-tests in cmakelists file) 28 | class Environment : public ::testing::Environment { 29 | public: 30 | ~Environment() override { 31 | } 32 | 33 | // Override this to define how to set up the environment. 34 | void SetUp() override { 35 | auto options = std::make_shared(); 36 | options -> logger = std::make_shared(LogLevel::DEBUG); 37 | ASSERT_EQ(init(options), Error::Ok); 38 | } 39 | 40 | // Override this to define how to tear down the environment. 41 | void TearDown() override { 42 | shutdown(); 43 | } 44 | }; 45 | 46 | 47 | int main(int argc, char **argv) { 48 | ::testing::InitGoogleTest(&argc, argv); 49 | ::testing::AddGlobalTestEnvironment(new Environment); 50 | return RUN_ALL_TESTS(); 51 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/error.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include "nv_attestation/error.h" 20 | #include "nv_attestation/log.h" 21 | 22 | namespace nvattestation { 23 | 24 | // Define the thread-local variable. 25 | // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) 26 | thread_local std::vector ErrorStack::m_thread_errors; 27 | 28 | std::vector& ErrorStack::get_thread_errors() { 29 | return m_thread_errors; 30 | } 31 | 32 | void ErrorStack::push(Error code, const std::string& message) { 33 | get_thread_errors().emplace_back(ErrorRecord{code, message}); 34 | } 35 | 36 | bool ErrorStack::has_errors() { 37 | return !get_thread_errors().empty(); 38 | } 39 | 40 | ErrorRecord ErrorStack::pop() { 41 | auto& errors = get_thread_errors(); 42 | if (errors.empty()) { 43 | return {Error::Ok, ""}; 44 | } 45 | ErrorRecord err = errors.back(); 46 | errors.pop_back(); 47 | return err; 48 | } 49 | 50 | ErrorRecord ErrorStack::peek() { 51 | auto& errors = get_thread_errors(); 52 | if (errors.empty()) { 53 | return {Error::Ok, ""}; 54 | } 55 | return errors.back(); 56 | } 57 | 58 | void ErrorStack::clear() { 59 | get_thread_errors().clear(); 60 | } 61 | 62 | Error nv_get_error() { 63 | return ErrorStack::pop().code; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /nv-attestation-cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(nvattest VERSION 0.1.0) 3 | 4 | option(BUILD_TESTING "Build tests" OFF) 5 | option(USE_SYSTEM_NVAT "Compile and link to the system nvat library. If OFF, nvat will be built from source." OFF) 6 | 7 | set(CMAKE_CXX_STANDARD 14) 8 | set(CMAKE_COMPILE_WARNING_AS_ERROR ON) 9 | 10 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0") 11 | 12 | include(CTest) 13 | include(GNUInstallDirs) 14 | include(FetchContent) 15 | 16 | FetchContent_Declare( 17 | CLI11 18 | GIT_REPOSITORY https://github.com/CLIUtils/CLI11.git 19 | GIT_TAG v2.3.2 20 | ) 21 | 22 | FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz EXCLUDE_FROM_ALL) 23 | FetchContent_MakeAvailable(CLI11 json) 24 | 25 | add_executable(nvattest 26 | src/main.cpp 27 | src/version.cpp 28 | src/attest.cpp 29 | src/collect_evidence.cpp 30 | src/utils.cpp 31 | ) 32 | 33 | find_package(spdlog REQUIRED) 34 | 35 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.toml 36 | ${CMAKE_CURRENT_BINARY_DIR}/config.toml 37 | COPYONLY) 38 | 39 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/version_config.h.in 40 | ${CMAKE_CURRENT_BINARY_DIR}/version_config.h) 41 | 42 | if(USE_SYSTEM_NVAT) 43 | find_package(nvat REQUIRED) 44 | else() 45 | add_subdirectory( 46 | "${CMAKE_CURRENT_SOURCE_DIR}/../nv-attestation-sdk-cpp" # Source directory 47 | "${CMAKE_CURRENT_BINARY_DIR}/nv-attestation-sdk-build" # Binary directory 48 | ) 49 | add_library(nvat::nvat ALIAS nvat) 50 | endif() 51 | 52 | target_link_libraries(nvattest PRIVATE 53 | nvat::nvat 54 | nlohmann_json::nlohmann_json 55 | CLI11::CLI11 56 | spdlog::spdlog 57 | ) 58 | 59 | target_include_directories(nvattest PRIVATE 60 | ${CMAKE_CURRENT_SOURCE_DIR}/src 61 | ${CMAKE_CURRENT_BINARY_DIR} 62 | ) 63 | 64 | if(BUILD_TESTING) 65 | enable_testing() 66 | add_subdirectory(tests) 67 | endif() 68 | 69 | install(TARGETS nvattest DESTINATION ${CMAKE_INSTALL_BINDIR}) 70 | 71 | include(CPack) 72 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/integration-tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(nv-attestation-integration-tests) 3 | 4 | # todo(p3): integration tests is currently not used. keeping the folder structure for now, in case we need to add any more in the future 5 | # if after a few weeks of development this becomes unecessary, this entire folder can be removed 6 | find_package(GTest REQUIRED) 7 | 8 | option(SANITIZER "Select a sanitizer" OFF) 9 | 10 | add_executable(nv-attestation-integration-tests 11 | main.cpp 12 | gpu_evidence_test.cpp 13 | switch_evidence_test.cpp 14 | ) 15 | 16 | target_include_directories(nv-attestation-integration-tests PRIVATE 17 | nv-attestation 18 | ) 19 | 20 | if (SANITIZER) 21 | target_compile_options(nv-attestation-integration-tests PRIVATE -fsanitize=${SANITIZER} -fno-sanitize-recover=all) 22 | target_link_options(nv-attestation-integration-tests PRIVATE -fsanitize=${SANITIZER} -fno-sanitize-recover=all) 23 | endif() 24 | target_compile_options(nv-attestation-integration-tests PRIVATE -Wno-unused -Wno-c++17-attribute-extensions) 25 | 26 | find_package(OpenSSL REQUIRED) 27 | find_package(spdlog REQUIRED) 28 | find_package(xmlsec REQUIRED) 29 | FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz) 30 | FetchContent_MakeAvailable(json) 31 | 32 | 33 | target_link_libraries(nv-attestation-integration-tests PRIVATE 34 | GTest::gtest 35 | nlohmann_json::nlohmann_json 36 | ) 37 | 38 | if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 39 | # CMake file is being run on its own (standalone) 40 | find_package(nvat REQUIRED) 41 | target_link_libraries(nv-attestation-integration-tests PRIVATE nvat::nvat) 42 | target_include_directories(nv-attestation-unit-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) 43 | else() 44 | # CMake file is being invoked as part of subdirectory from another CMake file 45 | target_link_libraries(nv-attestation-integration-tests PRIVATE nvat) 46 | target_include_directories(nv-attestation-integration-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) 47 | endif() 48 | 49 | include(GoogleTest) 50 | gtest_discover_tests(nv-attestation-integration-tests PROPERTIES LABELS "integration") -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/integration-tests/gpu_evidence_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "nv_attestation/gpu/nvml_client.h" 23 | #include "nv_attestation/gpu/evidence.h" 24 | 25 | using namespace nvattestation; 26 | 27 | TEST(NvmlIntegration, InitAndShutdown) { 28 | ASSERT_EQ(init_nvml(), Error::Ok); 29 | shutdown_nvml(); 30 | } 31 | 32 | TEST(NvmlIntegration, GetDriverVersion) { 33 | ASSERT_EQ(init_nvml(), Error::Ok); 34 | std::string driver_version{}; 35 | ASSERT_EQ(get_driver_version(driver_version), Error::Ok); 36 | ASSERT_FALSE(driver_version.empty()); 37 | shutdown_nvml(); 38 | } 39 | 40 | TEST(NvmlIntegration, NvmlEvidenceCollectorGetEvidence) { 41 | ASSERT_EQ(init_nvml(), Error::Ok); 42 | NvmlEvidenceCollector collector; 43 | std::vector nonce(32, 0); 44 | std::vector> evidence; 45 | Error error = collector.get_evidence(nonce, evidence); 46 | ASSERT_EQ(error, Error::Ok); 47 | ASSERT_FALSE(evidence.empty()); 48 | for (const auto& ev : evidence) { 49 | ASSERT_FALSE(to_string(ev->get_gpu_architecture()).empty()); 50 | ASSERT_GT(ev->get_board_id(), 0u); 51 | ASSERT_FALSE(ev->get_uuid().empty()); 52 | ASSERT_FALSE(ev->get_vbios_version().empty()); 53 | ASSERT_FALSE(ev->get_driver_version().empty()); 54 | ASSERT_FALSE(ev->get_attestation_report().empty()); 55 | } 56 | shutdown_nvml(); 57 | } 58 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/nv_jwt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "nv_attestation/error.h" 24 | #include "nv_attestation/nv_http.h" 25 | #include "nlohmann/json.hpp" 26 | 27 | namespace nvattestation { 28 | 29 | class Jwk { 30 | public: 31 | std::string kid; 32 | std::string pem_public_key; 33 | }; 34 | 35 | class JwkStore { 36 | public: 37 | static const long long DEFAULT_JWKS_CACHE_DURATION_MS = 900000; // 15 minutes 38 | 39 | JwkStore() {} 40 | static Error init_from_env( 41 | std::shared_ptr& jwk_store, 42 | const std::string& jwks_url, 43 | const std::string& service_key, 44 | const HttpOptions& http_options, 45 | long long cache_duration_ms = DEFAULT_JWKS_CACHE_DURATION_MS 46 | ); 47 | ~JwkStore() = default; 48 | Error get_jwk_by_kid(const std::string& kid, Jwk& out_jwk); 49 | private: 50 | std::mutex m_lock; 51 | std::string m_jwks_url; 52 | long long m_cache_duration_ms; // max time to retain the JWK set 53 | long long m_last_update_unix_ms; // last time cache was updated, as a unix timestamp 54 | std::unordered_map m_jwks; 55 | NvHttpClient m_http_client; 56 | 57 | Error refresh_jwks(); 58 | }; 59 | 60 | 61 | class NvJwt { 62 | public: 63 | static Error validate_and_decode( 64 | const std::string &jwt_token, 65 | std::shared_ptr& jwk_store, 66 | std::string &eat_issuer, 67 | std::string &out_payload 68 | ); 69 | }; 70 | 71 | } // namespace nvattestation -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/examples/attest-minimal/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | /* 22 | * Minimal GPU Attestation Example 23 | * To run: gcc -o attest-minimal main.c -lnvat && ./attest-minimal 24 | */ 25 | 26 | int main(void) { 27 | nvat_sdk_opts_t opts=NULL; 28 | nvat_attestation_ctx_t ctx=NULL; 29 | nvat_str_t detached_eat=NULL; 30 | nvat_claims_collection_t claims=NULL; 31 | char *claims_data=NULL; 32 | char *detached_eat_data = NULL; 33 | nvat_str_t claims_json=NULL; 34 | nvat_str_t detached_eat_str=NULL; 35 | 36 | // Initialize SDK 37 | nvat_sdk_opts_create(&opts); 38 | nvat_sdk_init(opts); 39 | 40 | // Create attestation context 41 | nvat_attestation_ctx_create(&ctx); 42 | 43 | // Perform attestation 44 | if (nvat_attest_device(ctx, NULL, &detached_eat, &claims) != NVAT_RC_OK) { 45 | fprintf(stderr, "Attestation failed\n"); 46 | // free opts and ctx 47 | return 1; 48 | } 49 | 50 | // Display claims 51 | // The return codes must be checked for errors and resources 52 | // must be freed appropriately. 53 | nvat_claims_collection_serialize_json(claims, &claims_json); 54 | nvat_str_get_data(claims_json, &claims_data); 55 | printf("Claims: \n%s\n", claims_data); 56 | 57 | // Display detached EAT 58 | nvat_str_get_data(detached_eat, &detached_eat_data); 59 | printf("Detached EAT: \n%s\n", detached_eat_data); 60 | 61 | // Cleanup 62 | nvat_str_free(&claims_json); 63 | nvat_claims_collection_free(&claims); 64 | nvat_str_free(&detached_eat); 65 | nvat_attestation_ctx_free(&ctx); 66 | nvat_sdk_opts_free(&opts); 67 | nvat_sdk_shutdown(); 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/spdm/spdm_req.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "nv_attestation/error.h" 27 | #include "nv_attestation/utils.h" 28 | 29 | namespace nvattestation { 30 | 31 | class SpdmMeasurementRequestMessage11 { 32 | static const size_t kSpdmVersionSize = 1; 33 | static const size_t kRequestResponseCodeSize = 1; 34 | static const size_t kParam1Size = 1; 35 | static const size_t kParam2Size = 1; 36 | static const size_t kNonceSize = 32; 37 | static const size_t kSlotIDParamSize = 1; 38 | static const size_t kRequestLength = 37; // 1 + 1 + 1 + 1 + 32 + 1 39 | public: 40 | static Error create(const std::vector& request_data, SpdmMeasurementRequestMessage11& out_message); 41 | 42 | // Getter methods 43 | uint8_t get_spdm_version() const { return m_spdm_version; } 44 | uint8_t get_request_response_code() const { return m_request_response_code; } 45 | uint8_t get_param1() const { return m_param1; } 46 | uint8_t get_param2() const { return m_param2; } 47 | const std::array& get_nonce() const { return m_nonce; } 48 | uint8_t get_slot_id_param() const { return m_slot_id_param; } 49 | static size_t get_request_length() { return kRequestLength; } 50 | 51 | private: 52 | 53 | uint8_t m_spdm_version; 54 | uint8_t m_request_response_code; 55 | uint8_t m_param1; 56 | uint8_t m_param2; 57 | std::array m_nonce; 58 | uint8_t m_slot_id_param; 59 | 60 | Error parse(const std::vector& request_data); 61 | 62 | }; 63 | 64 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/rego_engine/regorus_rego_engine_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | //stdlibs 19 | #include 20 | #include 21 | 22 | //third party 23 | #include "gtest/gtest.h" 24 | #include "gmock/gmock.h" 25 | #include "nlohmann/json.hpp" 26 | 27 | //this sdk 28 | #include "../src/internal/rego_engine/rego_engine.h" 29 | 30 | using namespace nvattestation; 31 | using ::testing::Return; 32 | using ::testing::_; 33 | 34 | class RegorusRegoEngineTest : public ::testing::Test { 35 | protected: 36 | static constexpr const char* VALID_POLICY = R"( 37 | package test 38 | default allow := false 39 | allow { 40 | input.user == "admin" 41 | } 42 | )"; 43 | 44 | static constexpr const char* INVALID_POLICY = R"( 45 | package test 46 | default allow := false 47 | allow { 48 | this is not valid Rego 49 | } 50 | )"; 51 | 52 | static constexpr const char* VALID_INPUT = R"( 53 | { 54 | "user": "admin" 55 | } 56 | )"; 57 | 58 | static constexpr const char* VALID_ENTRY_POINT = "data.test.allow"; 59 | }; 60 | 61 | TEST_F(RegorusRegoEngineTest, SuccessfullyEvaluatePolicy) { 62 | RegorusRegoEngine engine; 63 | auto result = engine.evaluate_policy( 64 | VALID_POLICY, VALID_INPUT, VALID_ENTRY_POINT); 65 | 66 | // Regorus returns results as JSON array. 67 | auto j = nlohmann::json::parse(*result); 68 | auto evaluation_result = j["result"][0]["expressions"][0]["value"]; 69 | 70 | EXPECT_EQ(evaluation_result, true); 71 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/sample_attestation_data/hopperClaimsv3_decoded.json: -------------------------------------------------------------------------------- 1 | { 2 | "GPU-0": { 3 | "x-nvidia-gpu-driver-rim-schema-validated": true, 4 | "iss": "https://nras.attestation.nvidia.com", 5 | "eat_nonce": "931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb", 6 | "x-nvidia-gpu-vbios-rim-signature-verified": true, 7 | "x-nvidia-gpu-vbios-rim-fetched": true, 8 | "exp": 1749605458, 9 | "x-nvidia-gpu-driver-rim-version-match": true, 10 | "iat": 1749601858, 11 | "ueid": "478176379286082186618948445787393647364802107249", 12 | "jti": "833480c9-6796-4fe4-b6ad-e9a58d7a67b2", 13 | "x-nvidia-gpu-attestation-report-nonce-match": true, 14 | "x-nvidia-gpu-vbios-index-no-conflict": true, 15 | "secboot": true, 16 | "x-nvidia-gpu-driver-rim-cert-chain": { 17 | "x-nvidia-cert-status": "valid", 18 | "x-nvidia-cert-ocsp-status": "good", 19 | "x-nvidia-cert-expiration-date": "2026-06-01T02:08:29Z", 20 | "x-nvidia-cert-revocation-reason": null 21 | }, 22 | "x-nvidia-gpu-vbios-rim-cert-chain": { 23 | "x-nvidia-cert-status": "valid", 24 | "x-nvidia-cert-ocsp-status": "good", 25 | "x-nvidia-cert-expiration-date": "2026-02-22T23:17:58Z", 26 | "x-nvidia-cert-revocation-reason": null 27 | }, 28 | "x-nvidia-gpu-attestation-report-parsed": true, 29 | "x-nvidia-gpu-attestation-report-cert-chain": { 30 | "x-nvidia-cert-status": "valid", 31 | "x-nvidia-cert-ocsp-status": "good", 32 | "x-nvidia-cert-expiration-date": "9999-12-31T23:59:59Z", 33 | "x-nvidia-cert-revocation-reason": null 34 | }, 35 | "x-nvidia-gpu-driver-rim-signature-verified": true, 36 | "x-nvidia-gpu-arch-check": true, 37 | "x-nvidia-gpu-vbios-rim-version-match": true, 38 | "x-nvidia-attestation-warning": null, 39 | "nbf": 1749601858, 40 | "x-nvidia-gpu-driver-version": "550.90.07", 41 | "x-nvidia-gpu-driver-rim-measurements-available": true, 42 | "x-nvidia-gpu-attestation-report-signature-verified": true, 43 | "hwmodel": "GH100 A01 GSP BROM", 44 | "dbgstat": "disabled", 45 | "x-nvidia-gpu-driver-rim-fetched": true, 46 | "x-nvidia-gpu-attestation-report-cert-chain-fwid-match": true, 47 | "oemid": "5703", 48 | "x-nvidia-gpu-vbios-rim-schema-validated": true, 49 | "measres": "success", 50 | "x-nvidia-gpu-vbios-version": "96.00.9F.00.01", 51 | "x-nvidia-gpu-vbios-rim-measurements-available": true 52 | } 53 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/CPackConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # TOC 2 | # 1. Generator-agnostic options 3 | # 1.1 Component-agnostic options 4 | # 1.2 Development component options 5 | # 1.3 Runtime component options 6 | # 2. Archive generator options 7 | # 3. DEB generator options 8 | # 3.1 Component-agnostic options 9 | # 3.2 Development component options 10 | # 3.3 Runtime component options 11 | 12 | # 1. Generator-agnostic options 13 | # 1.1 Generator-agnostic component-agnostic options 14 | set(CPACK_PACKAGE_CONTACT 15 | "NVIDIA Attestation Team " 16 | ) 17 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "NVIDIA Attestation SDK Library") 18 | set(CPACK_SOURCE_IGNORE_FILES 19 | "[.]git/" 20 | "build/" 21 | ".*~$" 22 | ) 23 | 24 | # Consider adding a longer CPACK_PACKAGE_DESCRIPTION_FILE pointing to a 25 | # description text file 26 | 27 | # 1.2 Generator-agnostic development specific options 28 | set(CPACK_COMPONENT_DEVELOPMENT_DESCRIPTION 29 | "NVIDIA Attestation SDK Headers and CMake files" 30 | ) 31 | set(CPACK_COMPONENT_DEVELOPMENT_DISPLAY_NAME "NV Attestation Development Files") 32 | 33 | # 1.3 Generator-agnostic runtime specific options 34 | set(CPACK_COMPONENT_RUNTIME_DISPLAY_NAME "NV Attestation Runtime") 35 | set(CPACK_COMPONENT_RUNTIME_DESCRIPTION "NVIDIA Attestation SDK Shared Library") 36 | 37 | # 2. Archive generator options 38 | set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) 39 | 40 | # 3. DEB generator options 41 | # 3.1 DEB generator component-agnostic options 42 | set(CPACK_DEB_COMPONENT_INSTALL ON) 43 | set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) 44 | set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) 45 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER 46 | "NVIDIA Attestation Team " 47 | ) 48 | set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) 49 | 50 | # 3.2 DEB generator development component options 51 | set(CPACK_DEBIAN_DEVELOPMENT_PACKAGE_NAME 52 | "libnv-attestation@NV_ATTESTATION_SOVERSION@-dev") 53 | 54 | # 3.3 DEB generator runtime component options 55 | # Generate shlibs file for the runtime package (recommended) 56 | set(CPACK_DEBIAN_RUNTIME_PACKAGE_NAME 57 | "libnv-attestation@NV_ATTESTATION_SOVERSION@" 58 | ) 59 | # Dependencies for the runtime package will be calculated automatically 60 | 61 | # ----------------------------------------------------------------------------- 62 | 63 | set(CPACK_PROPERTIES_FILE "@CMAKE_BINARY_DIR@/CPackProperties.cmake") 64 | 65 | @_CPACK_OTHER_VARIABLES_@ 66 | 67 | include("${CPACK_PROPERTIES_FILE}" OPTIONAL) 68 | -------------------------------------------------------------------------------- /nv-attestation-cli/tests/test_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "gtest/gtest.h" 25 | 26 | class CliTest : public ::testing::Test {}; 27 | 28 | inline std::string exec_and_capture_output(const std::string& command, int& exit_code) { 29 | std::array buffer{}; 30 | std::string result; 31 | FILE* pipe = popen((command + " 2>&1").c_str(), "r"); 32 | if (!pipe) { 33 | exit_code = -1; 34 | return result; 35 | } 36 | while (fgets(buffer.data(), static_cast(buffer.size()), pipe) != nullptr) { 37 | result.append(buffer.data()); 38 | } 39 | int status = pclose(pipe); 40 | if (WIFEXITED(status)) { 41 | exit_code = WEXITSTATUS(status); 42 | } else { 43 | exit_code = -1; 44 | } 45 | return result; 46 | } 47 | 48 | inline bool extract_json_object(const std::string& input, std::string& json_out) { 49 | // Find the last balanced JSON object by scanning from the end and matching braces 50 | if (input.empty()) return false; 51 | std::size_t end_pos = std::string::npos; 52 | int depth = 0; 53 | for (std::size_t i = input.size(); i-- > 0;) { 54 | const char c = input[i]; 55 | if (c == '}') { 56 | if (end_pos == std::string::npos) { 57 | end_pos = i; 58 | } 59 | depth++; 60 | } else if (c == '{' && depth > 0) { 61 | depth--; 62 | if (depth == 0 && end_pos != std::string::npos) { 63 | json_out = input.substr(i, end_pos - i + 1); 64 | return true; 65 | } 66 | } 67 | } 68 | return false; 69 | } 70 | -------------------------------------------------------------------------------- /nv-attestation-cli/src/collect_evidence.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | #include 20 | #include 21 | #include "nlohmann/json.hpp" 22 | 23 | #include "CLI/CLI.hpp" 24 | #include "nvat.h" 25 | #include "nvattest_options.h" 26 | 27 | namespace nvattest { 28 | /** 29 | * @brief Represents the output of the 'collect-evidence' CLI subcommand. 30 | * 31 | * Encapsulates the evidence collection results and provides a way to serialize it into JSON. 32 | */ 33 | class CollectEvidenceOutput { 34 | public: 35 | int result_code; 36 | std::string evidences; 37 | 38 | CollectEvidenceOutput(const int result_code); 39 | CollectEvidenceOutput(const int result_code, const std::string& evidences); 40 | nlohmann::json to_json() const; 41 | }; 42 | 43 | /** 44 | * @brief Creates and adds the 'collect-evidence' subcommand to the main CLI application. 45 | * 46 | * @param app The CLI11 application to which the subcommand will be added. 47 | * @return Pointer to the created CLI11 subcommand. 48 | */ 49 | CLI::App* create_collect_evidence_subcommand( 50 | CLI::App& app, 51 | EvidenceCollectionOptions& evidence_collection_options 52 | ); 53 | 54 | /** 55 | * @brief Handles the logic when the 'collect-evidence' subcommand is invoked. 56 | * 57 | * @param device String specifying which devices to use ("gpu", "nvswitch", etc.). 58 | * @param nonce Nonce for the attestation (in hex format). 59 | * @return Exit code for the subcommand handler (0 = success, 1 = failure). 60 | */ 61 | int handle_collect_evidence_subcommand( 62 | const EvidenceCollectionOptions& evidence_collection_options, 63 | const CommonOptions& common_options 64 | ); 65 | 66 | } 67 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/internal/certs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | 20 | namespace nvattestation 21 | { 22 | const std::string RIM_ROOT_CERT = R"(-----BEGIN CERTIFICATE----- 23 | MIICKTCCAbCgAwIBAgIQRdrjoA5QN73fh1N17LXicDAKBggqhkjOPQQDAzBFMQsw 24 | CQYDVQQGEwJVUzEPMA0GA1UECgwGTlZJRElBMSUwIwYDVQQDDBxOVklESUEgQ29S 25 | SU0gc2lnbmluZyBSb290IENBMCAXDTIzMDMxNjE1MzczNFoYDzIwNTMwMzA4MTUz 26 | NzM0WjBFMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGTlZJRElBMSUwIwYDVQQDDBxO 27 | VklESUEgQ29SSU0gc2lnbmluZyBSb290IENBMHYwEAYHKoZIzj0CAQYFK4EEACID 28 | YgAEuECyi9vNM+Iw2lfUzyBldHAwaC1HF7TCgp12QcEyUTm3Tagxwr48d55+K2VI 29 | lWYIDk7NlAIQdcV/Ff7euGLI+Qauj93HsSI4WX298PpW54RTgz9tC+Q684caR/BX 30 | WEeZo2MwYTAdBgNVHQ4EFgQUpaXrOPK4ZDAk08DBskn594zeZjAwHwYDVR0jBBgw 31 | FoAUpaXrOPK4ZDAk08DBskn594zeZjAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B 32 | Af8EBAMCAQYwCgYIKoZIzj0EAwMDZwAwZAIwHGDyscDP6ihHqRvZlI3eqZ4YkvjE 33 | 1duaN84tAHRVgxVMvNrp5Tnom3idHYGW/dskAjATvjIx6VzHm/4e2GiZAyZEIUBD 34 | OKPzp5ei/A0iUZpdvngenDwV8Qa/wGdiTmJ7Bp4= 35 | -----END CERTIFICATE-----)"; 36 | 37 | const std::string DEVICE_ROOT_CERT = R"(-----BEGIN CERTIFICATE----- 38 | MIICCzCCAZCgAwIBAgIQLTZwscoQBBHB/sDoKgZbVDAKBggqhkjOPQQDAzA1MSIw 39 | IAYDVQQDDBlOVklESUEgRGV2aWNlIElkZW50aXR5IENBMQ8wDQYDVQQKDAZOVklE 40 | SUEwIBcNMjExMTA1MDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMDUxIjAgBgNVBAMM 41 | GU5WSURJQSBEZXZpY2UgSWRlbnRpdHkgQ0ExDzANBgNVBAoMBk5WSURJQTB2MBAG 42 | ByqGSM49AgEGBSuBBAAiA2IABA5MFKM7+KViZljbQSlgfky/RRnEQScW9NDZF8SX 43 | gAW96r6u/Ve8ZggtcYpPi2BS4VFu6KfEIrhN6FcHG7WP05W+oM+hxj7nyA1r1jkB 44 | 2Ry70YfThX3Ba1zOryOP+MJ9vaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B 45 | Af8EBAMCAQYwHQYDVR0OBBYEFFeF/4PyY8xlfWi3Olv0jUrL+0lfMB8GA1UdIwQY 46 | MBaAFFeF/4PyY8xlfWi3Olv0jUrL+0lfMAoGCCqGSM49BAMDA2kAMGYCMQCPeFM3 47 | TASsKQVaT+8S0sO9u97PVGCpE9d/I42IT7k3UUOLSR/qvJynVOD1vQKVXf0CMQC+ 48 | EY55WYoDBvs2wPAH1Gw4LbcwUN8QCff8bFmV4ZxjCRr4WXTLFHBKjbfneGSBWwA= 49 | -----END CERTIFICATE-----)"; 50 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/internal/debug.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | # pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include // Include for std::ostringstream if needed elsewhere, or consider simplifying string creation 25 | 26 | #include "nv_attestation/nv_types.h" 27 | 28 | namespace nvattestation { 29 | 30 | // Helper function to get Subject and Issuer of an X509 certificate as a string 31 | inline std::string get_cert_subject_issuer_str(X509 *cert) { 32 | if (!cert) { 33 | return "Subject: , Issuer: "; 34 | } 35 | 36 | nv_unique_ptr bio_out(BIO_new(BIO_s_mem())); 37 | if (!bio_out) { 38 | return "Subject: , Issuer: "; 39 | } 40 | 41 | std::string result = "Subject: "; 42 | if (!X509_NAME_print_ex(bio_out.get(), X509_get_subject_name(cert), 0, XN_FLAG_ONELINE)) { 43 | return "Subject: "; 44 | } 45 | BUF_MEM *bio_buf = nullptr; 46 | BIO_get_mem_ptr(bio_out.get(), &bio_buf); 47 | if (bio_buf && bio_buf->data && bio_buf->length > 0) { 48 | result.append(bio_buf->data, bio_buf->length); 49 | } else { 50 | result.append(""); 51 | } 52 | BIO_reset(bio_out.get()); // Reset BIO for next use 53 | 54 | result += ", Issuer: "; 55 | if (!X509_NAME_print_ex(bio_out.get(), X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE)) { 56 | return "Issuer: "; 57 | } 58 | BIO_get_mem_ptr(bio_out.get(), &bio_buf); // Re-get buffer pointer after write 59 | if (bio_buf && bio_buf->data && bio_buf->length > 0) { 60 | result.append(bio_buf->data, bio_buf->length); 61 | } else { 62 | result.append(""); 63 | } 64 | 65 | return result; 66 | } 67 | 68 | } // namespace nvattestation 69 | 70 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/internal/rego_engine/rego_engine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace nvattestation { 25 | 26 | /** 27 | * Models a Rego evaluation engine by exposing functions to operate on Rego policy documents 28 | */ 29 | class RegoEngine { 30 | public: 31 | virtual ~RegoEngine() = default; 32 | 33 | /** 34 | * @brief Evaluates a given Rego policy with the provided input and entrypoint. 35 | * 36 | * This function takes a Rego policy, an input JSON string, and an entrypoint. 37 | * It evaluates the policy against the input using the specified entrypoint and 38 | * returns the result as a JSON-formatted string wrapped in an `EvaluationResult` object. 39 | * 40 | * @param policy A string containing the Rego policy to be evaluated. 41 | * @param input A string containing the input data in JSON format. 42 | * This input is passed to the policy during evaluation. 43 | * @param entrypoint A string specifying the entrypoint for evaluation. This 44 | * determines which part of the policy is evaluated. 45 | * 46 | * @return A JSON-formatted string containing the evaluation result, if successful. nullptr if 47 | * the policy failed to evaluate then the 48 | */ 49 | virtual std::unique_ptr evaluate_policy(const std::string &policy, const std::string &input, const std::string& entrypoint) = 0; 50 | }; 51 | 52 | 53 | /** 54 | * Facade of the [regorus](https://github.com/microsoft/regorus/) Rego interpreter library 55 | */ 56 | class RegorusRegoEngine : public RegoEngine{ 57 | public: 58 | std::unique_ptr evaluate_policy(const std::string &policy, const std::string &input, const std::string& entrypoint); 59 | }; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/rego_engine/regorus_rego_engine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "regorus.ffi.hpp" 24 | 25 | #include "nv_attestation/log.h" 26 | 27 | #include "internal/rego_engine/regorus.hpp" 28 | #include "internal/rego_engine/rego_engine.h" 29 | 30 | namespace nvattestation { 31 | 32 | std::unique_ptr RegorusRegoEngine::evaluate_policy( 33 | const std::string &policy, 34 | const std::string &input, 35 | const std::string &entrypoint) { 36 | 37 | regorus::Engine engine; 38 | 39 | regorus::Result set_rego_v0_result = engine.set_rego_v0(true); 40 | if (!set_rego_v0_result) { 41 | LOG_PUSH_ERROR(Error::PolicyEvaluationError, std::string("Failed to set the Rego version: ") + set_rego_v0_result.error()); 42 | return nullptr; 43 | } 44 | 45 | regorus::Result add_policy_result = engine.add_policy("policy.rego", policy.c_str()); 46 | if (!add_policy_result) { 47 | LOG_PUSH_ERROR(Error::PolicyEvaluationError, std::string("Failed to add the policy: ") + add_policy_result.error()); 48 | return nullptr; 49 | } 50 | 51 | regorus::Result set_input_json_result = engine.set_input_json(input.c_str()); 52 | if (!set_input_json_result) { 53 | LOG_PUSH_ERROR(Error::PolicyEvaluationError, std::string("Failed to set the input json: ") + set_input_json_result.error()); 54 | return nullptr; 55 | } 56 | 57 | regorus::Result evaluate_query_result = engine.eval_query(entrypoint.c_str()); 58 | if (!evaluate_query_result) { 59 | LOG_PUSH_ERROR(Error::PolicyEvaluationError, std::string("Failed to evaluate the policy: ") + evaluate_query_result.error()); 60 | return nullptr; 61 | } 62 | 63 | return std::make_unique(evaluate_query_result.output()); 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /nv-attestation-cli/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "nvat.h" 19 | #include 20 | #include 21 | #include "CLI/CLI.hpp" 22 | #include "version.h" 23 | #include "attest.h" 24 | #include "collect_evidence.h" 25 | #include "nvattest_options.h" 26 | #include "utils.h" 27 | 28 | #include "spdlog/spdlog.h" 29 | #include "spdlog/sinks/stdout_sinks.h" 30 | 31 | 32 | int main(int argc, char** argv) { 33 | // Configure logger 34 | auto console = spdlog::stdout_logger_mt("console"); 35 | spdlog::set_default_logger(console); 36 | spdlog::set_pattern("%v"); 37 | 38 | CLI::App app{"NVIDIA attestation CLI for collecting evidence and verifying device integrity in confidential computing environments"}; 39 | app.set_config("--config", "config.toml", "Read options from a TOML configuration file"); 40 | 41 | nvattest::EvidenceCollectionOptions evidence_collection_options; 42 | nvattest::EvidenceVerificationOptions evidence_verification_options; 43 | nvattest::EvidencePolicyOptions evidence_policy_options; 44 | nvattest::CommonOptions common_options; 45 | 46 | add_common_options(app, common_options); 47 | 48 | CLI::App* version_subcommand = nvattest::create_version_subcommand(app); 49 | CLI::App* attest_subcommand = nvattest::create_attest_subcommand(app, evidence_collection_options, evidence_verification_options, evidence_policy_options); 50 | CLI::App* collect_evidence_subcommand = nvattest::create_collect_evidence_subcommand(app, evidence_collection_options); 51 | 52 | CLI11_PARSE(app, argc, argv); 53 | 54 | // Dispatch subcommands 55 | if (version_subcommand->parsed()) { 56 | return nvattest::handle_version_subcommand(); 57 | } else if (attest_subcommand->parsed()) { 58 | return nvattest::handle_attest_subcommand(evidence_collection_options, evidence_verification_options, evidence_policy_options, common_options); 59 | } else if (collect_evidence_subcommand->parsed()) { 60 | return nvattest::handle_collect_evidence_subcommand(evidence_collection_options, common_options); 61 | } else { 62 | // Default behavior is to display the help message 63 | std::cout << app.help() << std::endl; 64 | } 65 | 66 | return 0; 67 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/cmake/Findxmlsec.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | 3 | if(PKG_CONFIG_FOUND) 4 | pkg_check_modules(Pc_xmlsec QUIET xmlsec1) 5 | pkg_check_modules(Pc_xmlsec_openssl QUIET xmlsec1-openssl) 6 | 7 | if (Pc_xmlsec_openssl_FOUND) 8 | list(APPEND xmlsec_COMPILE_DEFINITIONS ${Pc_xmlsec_openssl_CFLAGS_OTHER}) 9 | list(APPEND xmlsec_INCLUDE_DIRS ${Pc_xmlsec_openssl_INCLUDE_DIRS}) 10 | list(APPEND xmlsec_LIBRARY_DIRS ${Pc_xmlsec_openssl_LIBRARY_DIRS}) 11 | list(APPEND xmlsec_LIBRARIES ${Pc_xmlsec_openssl_LIBRARIES}) 12 | endif() 13 | 14 | if (NOT xmlsec_FIND_QUIETLY) 15 | if (Pc_xmlsec_FOUND) 16 | message(STATUS "Found xmlsec1 via pkg-config") 17 | else() 18 | message(STATUS "Not found xmlsec1 via pkg-config") 19 | endif() 20 | 21 | if (Pc_xmlsec_openssl_FOUND) 22 | message(STATUS "Found xmlsec1-openssl via pkg-config") 23 | message(STATUS "XMLSec CFLAGS: ${Pc_xmlsec_CFLAGS}") 24 | message(STATUS "XMLSec LDFLAGS: ${Pc_xmlsec_LDFLAGS}") 25 | else() 26 | message(STATUS "Not found xmlsec1-openssl via pkg-config") 27 | endif() 28 | endif() 29 | endif() 30 | 31 | if(CMAKE_VERSION VERSION_LESS 3.12.0) 32 | list(APPEND xmlsec_ROOT "$ENV{xmlsec_ROOT}") 33 | endif() 34 | 35 | list(APPEND xmlsec_ROOT "${xmlsec_ROOT_DIR}" "$ENV{xmlsec_ROOT_DIR}") 36 | list(REMOVE_ITEM xmlsec_ROOT "") 37 | list(REMOVE_DUPLICATES xmlsec_ROOT) 38 | 39 | find_path(xmlsec_INCLUDE_DIR 40 | NAMES xmlsec/xmlsec.h 41 | PATH_SUFFIXES xmlsec1 42 | PATHS "${xmlsec_ROOT}" 43 | HINTS "${Pc_xmlsec_INCLUDE_DIRS}" "${Pc_xmlsec_openssl_INCLUDE_DIRS}" 44 | ) 45 | 46 | find_library(xmlsec_LIBRARY 47 | NAMES xmlsec1 48 | PATHS "${xmlsec_ROOT}" 49 | HINTS ${Pc_xmlsec_LIBRARY_DIRS} 50 | ) 51 | 52 | find_library(xmlsec_OPENSSL_LIBRARY 53 | NAMES xmlsec1-openssl 54 | PATHS "${xmlsec_ROOT}" 55 | HINTS ${Pc_xmlsec_openssl_LIBRARY_DIRS} 56 | ) 57 | 58 | include(FindPackageHandleStandardArgs) 59 | find_package_handle_standard_args(xmlsec REQUIRED_VARS 60 | xmlsec_LIBRARY 61 | xmlsec_OPENSSL_LIBRARY 62 | xmlsec_INCLUDE_DIRS 63 | ) 64 | 65 | if(xmlsec_FOUND) 66 | if (NOT TARGET xmlsec::xmlsec) 67 | add_library(xmlsec::xmlsec UNKNOWN IMPORTED) 68 | set_target_properties(xmlsec::xmlsec PROPERTIES 69 | IMPORTED_LOCATION "${xmlsec_LIBRARY}" 70 | INTERFACE_COMPILE_OPTIONS "${Pc_xmlsec_CFLAGS}" 71 | INTERFACE_INCLUDE_DIRECTORIES "${xmlsec_INCLUDE_DIRS}" 72 | ) 73 | endif() 74 | 75 | if(NOT TARGET xmlsec::xmlsec-openssl) 76 | add_library(xmlsec::xmlsec-openssl UNKNOWN IMPORTED) 77 | set_target_properties(xmlsec::xmlsec-openssl PROPERTIES 78 | IMPORTED_LOCATION "${xmlsec_OPENSSL_LIBRARY}" 79 | INTERFACE_COMPILE_OPTIONS "${Pc_xmlsec_openssl_CFLAGS}" 80 | INTERFACE_INCLUDE_DIRECTORIES "${xmlsec_INCLUDE_DIR}" 81 | INTERFACE_LINK_LIBRARIES "${Pc_xmlsec_openssl_LIBRARIES}" 82 | INTERFACE_LINK_DIRECTORIES "${Pc_xmlsec_openssl_LIBRARY_DIRS}" 83 | ) 84 | endif() 85 | endif() 86 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/sample_attestation_data/switch_detached_eat.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | "JWT", 4 | "eyJraWQiOiJudi1lYXQta2lkLXN0Zy0yMDI1MDYyNzIzMTYzODQ5MS04NjcyZWE4OS1jMTRhLTQyMDItOTI0YS00ZTQyOTdiN2M3ZjEiLCJhbGciOiJFUzM4NCJ9.eyJzdWIiOiJOVklESUEtUExBVEZPUk0tQVRURVNUQVRJT04iLCJ4LW52aWRpYS12ZXIiOiIzLjAiLCJuYmYiOjE3NTExNTUwNjAsImlzcyI6Imh0dHBzOi8vbnJhcy5hdHRlc3RhdGlvbi1zdGcubnZpZGlhLmNvbSIsIngtbnZpZGlhLW92ZXJhbGwtYXR0LXJlc3VsdCI6dHJ1ZSwic3VibW9kcyI6eyJTV0lUQ0gtMCI6WyJESUdFU1QiLFsiU0hBLTI1NiIsIjE3Zjg0YjcwZjRkNTU0MzA2ZGY4ZjIyN2UxY2IyZjgyZjYxOTZlOTIyMGE5ZmRiYTA5MWQyY2NhNGFlYzkxN2QiXV19LCJlYXRfbm9uY2UiOiI5MzFkOGRkMGFkZDIwM2FjM2Q4YjRmYmRlNzVlMTE1Mjc4ZWVmY2RjZWFjNWI4NzY3MWE3NDhmMzIzNjRkZmNiIiwiZXhwIjoxNzUxMTU4NjYwLCJpYXQiOjE3NTExNTUwNjAsImp0aSI6ImYyNmVlMDRmLTdjNGEtNDE1MS05ZWEyLWNhZjI2YzZjZDkzZCJ9.k120w3tVL-PY6VbX9gWx-VncLaqhXP2V19BWk5yrNxKGbUj8QpFa1O-dBhOisIjO_aN2VfDxcbiuWwV_qL8OU-fVl-NUN2ypWC0KM16QADGbR2DZvUCIBcYwSyZ1nbLt" 5 | ], 6 | { 7 | "SWITCH-0": "eyJraWQiOiJudi1lYXQta2lkLXN0Zy0yMDI1MDYyNzIzMTYzODQ5MS04NjcyZWE4OS1jMTRhLTQyMDItOTI0YS00ZTQyOTdiN2M3ZjEiLCJhbGciOiJFUzM4NCJ9.eyJ4LW52aWRpYS1zd2l0Y2gtYmlvcy1yaW0tZmV0Y2hlZCI6dHJ1ZSwieC1udmlkaWEtc3dpdGNoLWJpb3MtcmltLXNpZ25hdHVyZS12ZXJpZmllZCI6dHJ1ZSwieC1udmlkaWEtc3dpdGNoLWF0dGVzdGF0aW9uLXJlcG9ydC1jZXJ0LWNoYWluLWZ3aWQtbWF0Y2giOnRydWUsIngtbnZpZGlhLXN3aXRjaC1hdHRlc3RhdGlvbi1yZXBvcnQtc2lnbmF0dXJlLXZlcmlmaWVkIjp0cnVlLCJ4LW52aWRpYS1zd2l0Y2gtYmlvcy1yaW0tdmVyc2lvbi1tYXRjaCI6dHJ1ZSwieC1udmlkaWEtc3dpdGNoLWF0dGVzdGF0aW9uLXJlcG9ydC1wYXJzZWQiOnRydWUsImlzcyI6Imh0dHBzOi8vbnJhcy5hdHRlc3RhdGlvbi1zdGcubnZpZGlhLmNvbSIsImVhdF9ub25jZSI6IjkzMWQ4ZGQwYWRkMjAzYWMzZDhiNGZiZGU3NWUxMTUyNzhlZWZjZGNlYWM1Yjg3NjcxYTc0OGYzMjM2NGRmY2IiLCJ4LW52aWRpYS1zd2l0Y2gtYXR0ZXN0YXRpb24tcmVwb3J0LW5vbmNlLW1hdGNoIjp0cnVlLCJ4LW52aWRpYS1zd2l0Y2gtYXR0ZXN0YXRpb24tcmVwb3J0LWNlcnQtY2hhaW4iOnsieC1udmlkaWEtY2VydC1zdGF0dXMiOiJ2YWxpZCIsIngtbnZpZGlhLWNlcnQtb2NzcC1zdGF0dXMiOiJnb29kIiwieC1udmlkaWEtY2VydC1leHBpcmF0aW9uLWRhdGUiOiI5OTk5LTEyLTMxVDIzOjU5OjU5WiIsIngtbnZpZGlhLWNlcnQtcmV2b2NhdGlvbi1yZWFzb24iOm51bGx9LCJleHAiOjE3NTExNTg2NjAsImlhdCI6MTc1MTE1NTA2MCwidWVpZCI6IjY5NDkzMTE0Mzg4MDk4Mzg3Njc2NzA0NjgwMzQwMDk3NDg1NTQ0NTk3ODgzNjcxNiIsImp0aSI6IjEwMTJkOGIxLWI1MmQtNDg3MC05YjllLTZlZjZiMDViYTdmMiIsIngtbnZpZGlhLXN3aXRjaC1hcmNoLWNoZWNrIjp0cnVlLCJzZWNib290Ijp0cnVlLCJ4LW52aWRpYS1zd2l0Y2gtYmlvcy1yaW0tc2NoZW1hLXZhbGlkYXRlZCI6dHJ1ZSwieC1udmlkaWEtc3dpdGNoLWJpb3MtcmltLWNlcnQtY2hhaW4iOnsieC1udmlkaWEtY2VydC1zdGF0dXMiOiJ2YWxpZCIsIngtbnZpZGlhLWNlcnQtb2NzcC1zdGF0dXMiOiJnb29kIiwieC1udmlkaWEtY2VydC1leHBpcmF0aW9uLWRhdGUiOiIyMDI2LTA1LTIwVDE3OjU5OjA2WiIsIngtbnZpZGlhLWNlcnQtcmV2b2NhdGlvbi1yZWFzb24iOm51bGx9LCJ4LW52aWRpYS1hdHRlc3RhdGlvbi13YXJuaW5nIjpudWxsLCJuYmYiOjE3NTExNTUwNjAsImh3bW9kZWwiOiJMU18xMCBBMDEgRlNQIEJST00iLCJkYmdzdGF0IjoiZGlzYWJsZWQiLCJ4LW52aWRpYS1zd2l0Y2gtYmlvcy1yaW0tbWVhc3VyZW1lbnRzLWF2YWlsYWJsZSI6dHJ1ZSwib2VtaWQiOm51bGwsIm1lYXNyZXMiOiJzdWNjZXNzIiwieC1udmlkaWEtc3dpdGNoLWJpb3MtdmVyc2lvbiI6Ijk2LjEwLjU1LjAwLjAxIn0.HtRmy1Qq_f-ki8HJxY5HdTWjsTTOSdg0cQg3ffvrK8LZE54Odta_F1ttwtZRevwOvTl6o5QG5O5oMx3TZu5mqKoQsYhd7dLom7MsPX-5rcjEPhgCus-t0G34ZXzyRp-J" 8 | } 9 | ] -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/spdm/spdm_opaque_data_parser.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "nv_attestation/error.h" 29 | 30 | namespace nvattestation { 31 | 32 | 33 | class OpaqueFieldSizes { 34 | public: 35 | static constexpr size_t DATA_TYPE_SIZE = 2; 36 | static constexpr size_t DATA_SIZE_FIELD_SIZE = 2; 37 | }; 38 | 39 | 40 | // Define a type for storing the parsed opaque data fields. 41 | class ParsedOpaqueFieldData { 42 | public: 43 | ParsedOpaqueFieldData(); 44 | 45 | // Constructor for byte_vector 46 | ParsedOpaqueFieldData(uint16_t type, const std::vector& data); 47 | 48 | static Error create(const std::vector& data, uint16_t type, ParsedOpaqueFieldData& out_field); 49 | Error get_data(const std::vector*& out_data) const; 50 | uint16_t get_type() const; 51 | private: 52 | std::vector m_data; 53 | uint16_t m_type; // because data type size for opaque field is 2 bytes 54 | }; 55 | 56 | 57 | class OpaqueDataParser { 58 | public: 59 | /** 60 | * @brief Default constructor creates an empty parser. 61 | * Use the create() method to populate with data. 62 | */ 63 | OpaqueDataParser(); 64 | 65 | /** 66 | * @brief Factory method to create and parse opaque data. 67 | * @param opaque_raw_data The raw byte vector of the opaque data field. 68 | * @param out_parser Reference to OpaqueDataParser to populate. 69 | * @return Error::Ok if parsing is successful, appropriate error code otherwise. 70 | */ 71 | static Error create(const std::vector& opaque_raw_data, OpaqueDataParser& out_parser); 72 | Error get_all_fields(const std::vector*& out_fields) const; 73 | 74 | private: 75 | // Private constructor, use create() instead. 76 | Error parse(const std::vector& raw_data); 77 | std::vector m_fields; 78 | }; 79 | 80 | // Overload for printing the parsed opaque data (useful for debugging) 81 | std::ostream& operator<<(std::ostream& os, const OpaqueDataParser& parser); 82 | 83 | } // namespace nvattestation -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/include/environment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "nv_attestation/init.h" 8 | #include "nv_attestation/error.h" 9 | #include "nv_attestation/utils.h" 10 | #include "test_utils.h" 11 | 12 | using namespace nvattestation; 13 | 14 | class Environment : public ::testing::Environment { 15 | public: 16 | std::string test_mode; // "unit" or "integration" 17 | bool test_device_gpu=false; 18 | bool test_device_switch=false; 19 | std::string common_test_data_dir; 20 | std::string service_key = ""; 21 | ~Environment() override { 22 | } 23 | 24 | // Override this to define how to set up the environment. 25 | void SetUp() override { 26 | // Always run the certificate generation script (it will check if certs already exist) 27 | const std::string cert_dir = "testdata/x509_cert_chain/"; 28 | std::string command = "cd " + cert_dir + " && ./generate_test_certs.sh"; 29 | 30 | int result = std::system(command.c_str()); 31 | if (result != 0) { 32 | std::cerr << "Warning: Certificate generation script failed. Exit code: " << result << std::endl; 33 | } 34 | 35 | std::shared_ptr options = std::make_shared(); 36 | options -> logger = std::make_shared(LogLevel::TRACE); 37 | 38 | // read env variables used to configure the tests 39 | test_mode = get_env_or_default("TEST_MODE", "unit"); 40 | std::string test_devices_env = get_env_or_default("TEST_DEVICES", ""); 41 | std::stringstream ss(test_devices_env); 42 | std::string device; 43 | std::cout << "TEST_MODE: " << test_mode << std::endl; 44 | if (test_mode != "integration" && test_mode != "unit") { 45 | std::cerr << "Invalid test mode: " << test_mode << std::endl; 46 | exit(1); 47 | } 48 | 49 | while (std::getline(ss, device, ',')) { 50 | std::cout << "TEST_DEVICE: " << device << std::endl; 51 | if (test_mode == "integration" && (device != "gpu" && device != "nvswitch")) { 52 | std::cerr << "Invalid test device: " << device << std::endl; 53 | exit(1); 54 | } 55 | if (device == "gpu") { 56 | test_device_gpu = true; 57 | std::cout << "Initializing NVML" << std::endl; 58 | } 59 | if (device == "nvswitch") { 60 | test_device_switch = true; 61 | std::cout << "Initializing NSCQ" << std::endl; 62 | } 63 | } 64 | 65 | ASSERT_EQ(init(options), Error::Ok); 66 | 67 | std::string git_repo_root; 68 | ASSERT_EQ(get_git_repo_root(git_repo_root), Error::Ok); 69 | common_test_data_dir = git_repo_root + "/common-test-data"; 70 | 71 | 72 | service_key = get_env_or_default("NVAT_C_SDK_TEST_SERVICE_KEY", ""); 73 | ASSERT_FALSE(service_key.empty()) << "Service key is empty, please set NVAT_C_SDK_TEST_SERVICE_KEY environment variable"; 74 | } 75 | 76 | // Override this to define how to tear down the environment. 77 | void TearDown() override { 78 | shutdown(); 79 | } 80 | }; 81 | 82 | extern Environment* g_env; -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/claims_evaluator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | //third party 22 | #include 23 | 24 | //this SDK 25 | #include "nv_attestation/log.h" 26 | #include "nv_attestation/claims_evaluator.h" 27 | #include "internal/rego_engine/rego_engine.h" 28 | 29 | namespace nvattestation { 30 | 31 | 32 | class RegoClaimsEvaluator : public IClaimsEvaluator { 33 | private: 34 | std::string m_policy; 35 | RegorusRegoEngine m_engine; 36 | 37 | static constexpr const char* ENTRYPOINT = "data.policy.nv_match"; 38 | 39 | public: 40 | RegoClaimsEvaluator(const std::string& policy) : m_policy(policy) {} 41 | 42 | Error evaluate_claims(const ClaimsCollection& claims, bool& out_match) override { 43 | std::string json; 44 | Error error = claims.serialize_json(json); 45 | if (error != Error::Ok) { 46 | LOG_ERROR("Failed to serialize claims"); 47 | return error; 48 | } 49 | LOG_TRACE("--- Rego Policy ---" << std::endl << m_policy << "--- End Rego Policy ---"); 50 | auto evaluation_result = m_engine.evaluate_policy(m_policy, json, ENTRYPOINT); 51 | if (evaluation_result == nullptr) { 52 | return Error::PolicyEvaluationError; 53 | } 54 | 55 | try { 56 | LOG_TRACE("--- Policy evaluation result ---" << std::endl << *evaluation_result << "--- End Policy Evaluation Result ---"); 57 | auto json = nlohmann::json::parse(*evaluation_result); 58 | // Safely access nested members using .at() to throw if missing/wrong type 59 | out_match = json.at("result").at(0).at("expressions").at(0).at("value"); 60 | return Error::Ok; 61 | } catch (const nlohmann::json::exception& e) { 62 | LOG_ERROR(std::string("Failed to evaluate policy: ") + e.what()); 63 | // Even if JSON parsing fails, default to false instead of error 64 | out_match = false; 65 | return Error::Ok; 66 | } 67 | } 68 | }; 69 | 70 | std::shared_ptr ClaimsEvaluatorFactory::create_rego_claims_evaluator(const std::string &policy) { 71 | return std::make_shared(policy); 72 | } 73 | 74 | 75 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/verify.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "nvat.h" 21 | #include 22 | #include 23 | #include 24 | 25 | #include "nv_attestation/error.h" 26 | #include "nv_attestation/nv_jwt.h" 27 | #include 28 | #include "nv_attestation/gpu/claims.h" 29 | #include "nv_attestation/switch/claims.h" 30 | #include "nv_attestation/nv_http.h" 31 | 32 | namespace nvattestation 33 | { 34 | enum class VerifierType { 35 | Local, 36 | Remote, 37 | }; 38 | 39 | Error verifier_type_from_c(nvat_verifier_type_t c_type, VerifierType& out_type); 40 | std::string to_string(VerifierType verifier_type); 41 | 42 | class OcspVerifyOptions 43 | { 44 | private: 45 | bool m_nonce_enabled; 46 | bool m_allow_cert_hold; 47 | 48 | public: 49 | OcspVerifyOptions() : m_nonce_enabled(true), m_allow_cert_hold(false) {} 50 | void set_nonce_enabled(bool enabled); 51 | bool get_nonce_enabled() const; 52 | void set_allow_cert_hold(bool allow_cert_hold); 53 | bool get_allow_cert_hold() const; 54 | }; 55 | 56 | class EvidencePolicy { 57 | public: 58 | EvidencePolicy(): 59 | ocsp_options(OcspVerifyOptions()), 60 | gpu_claims_version(GpuClaimsVersion::V3), 61 | switch_claims_version(SwitchClaimsVersion::V3), 62 | verify_rim_signature(true) {} 63 | 64 | OcspVerifyOptions ocsp_options; 65 | GpuClaimsVersion gpu_claims_version; 66 | SwitchClaimsVersion switch_claims_version; 67 | bool verify_rim_signature; 68 | }; 69 | 70 | Error validate_and_decode_EAT( 71 | const SerializableDetachedEAT& detached_eat, 72 | std::shared_ptr& jwk_store, 73 | std::string& eat_issuer, 74 | NvHttpClient& http_client, 75 | std::vector& out_eat_nonce, 76 | std::unordered_map& out_claims 77 | ); 78 | 79 | class NRASAttestRequestV4 { 80 | public: 81 | std::string nonce; 82 | std::string arch; 83 | std::string claims_version; 84 | // vector of evidence and certificate chain 85 | std::vector> evidence_list; 86 | }; 87 | 88 | void to_json(nlohmann::json& json, const NRASAttestRequestV4& attest_request); 89 | 90 | } -------------------------------------------------------------------------------- /nv-attestation-cli/tests/environment.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | inline std::string get_env_or_default(const char* name, const char* default_value) { 29 | const char* env_val = std::getenv(name); 30 | if (env_val == nullptr || *env_val == '\0') { 31 | return std::string(default_value); 32 | } 33 | return std::string(env_val); 34 | } 35 | 36 | class Environment : public ::testing::Environment { 37 | public: 38 | std::string test_mode; // "unit" or "integration" 39 | bool test_device_gpu; 40 | bool test_device_switch; 41 | std::string service_key = ""; 42 | 43 | ~Environment() override = default; 44 | 45 | void SetUp() override { 46 | test_mode = get_env_or_default("TEST_MODE", "unit"); 47 | std::string test_devices_env = get_env_or_default("TEST_DEVICES", ""); 48 | std::stringstream ss(test_devices_env); 49 | std::string device; 50 | std::cout << "TEST_MODE: " << test_mode << std::endl; 51 | if (test_mode != "integration" && test_mode != "unit") { 52 | std::cerr << "Invalid test mode: " << test_mode << std::endl; 53 | exit(1); 54 | } 55 | 56 | while (std::getline(ss, device, ',')) { 57 | std::cout << "TEST_DEVICE: " << device << std::endl; 58 | if (test_mode == "integration" && (device != "gpu" && device != "nvswitch")) { 59 | std::cerr << "Invalid test device: " << device << std::endl; 60 | exit(1); 61 | } 62 | if (device == "gpu") { 63 | test_device_gpu = true; 64 | } 65 | if (device == "nvswitch") { 66 | test_device_switch = true; 67 | } 68 | } 69 | 70 | service_key = get_env_or_default("NVAT_C_SDK_TEST_SERVICE_KEY", ""); 71 | ASSERT_FALSE(service_key.empty()) << "Service key is empty, please set NVAT_C_SDK_TEST_SERVICE_KEY environment variable"; 72 | } 73 | 74 | void TearDown() override { 75 | // no teardown required 76 | } 77 | }; 78 | 79 | extern Environment* g_cli_env; 80 | -------------------------------------------------------------------------------- /nv-attestation-cli/src/utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "utils.h" 19 | 20 | namespace nvattest { 21 | void add_evidence_collection_options(CLI::App* app, EvidenceCollectionOptions& options) { 22 | app->add_option("--nonce", options.nonce, "Nonce for the attestation (in hex format). If not provided, a nonce will be generated.") 23 | ->default_val(""); 24 | app->add_option("--device", options.device, "Device to attest ('gpu', 'nvswitch')") 25 | ->check(CLI::IsMember({"gpu", "nvswitch"})) 26 | ->default_val("gpu"); 27 | } 28 | 29 | void add_evidence_policy_options(CLI::App* app, EvidencePolicyOptions& options) { 30 | } 31 | 32 | void add_evidence_verification_options(CLI::App* app, EvidenceVerificationOptions& options) { 33 | app->add_option("--verifier", options.verifier, "Verifier type ('local' or 'remote')") 34 | ->check(CLI::IsMember({"local", "remote"})) 35 | ->default_val("local"); 36 | app->add_option("--relying-party-policy", options.relying_party_policy, "Path to a local file which contains a Relying Party Rego policy")->default_val(""); 37 | app->add_option("--rim-url", options.rim_url, "Base URL for the NVIDIA RIM service")->default_val("https://rim.attestation.nvidia.com"); 38 | app->add_option("--ocsp-url", options.ocsp_url, "Base URL for the OCSP responder")->default_val("https://ocsp.ndis.nvidia.com"); 39 | app->add_option("--nras-url", options.nras_url, "Base URL for the NVIDIA Remote Attestation Service")->default_val("https://nras.attestation.nvidia.com"); 40 | app->add_option("--gpu-evidence", options.gpu_evidence, "Path to a local file which contains GPU evidence. Used instead of calling NVML")->default_val(""); 41 | app->add_option("--switch-evidence", options.switch_evidence, "Path to a local file which contains Switch evidence. Used instead of calling NSCQ")->default_val(""); 42 | app->add_option("--service-key", options.service_key, "Service key used to authenticate remote service calls to attestation services")->default_val(""); 43 | } 44 | 45 | void add_common_options(CLI::App& app, CommonOptions& options) { 46 | app.add_option("--log-level", options.log_level, "Log level ('trace', 'debug', 'info', 'warn', 'error', 'off')") 47 | ->check(CLI::IsMember({"trace", "debug", "info", "warn", "error", "off"})) 48 | ->default_val("warn"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/nv_http_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | 19 | #include "nlohmann/json.hpp" 20 | 21 | #include "nv_attestation/nv_http.h" 22 | #include "nv_attestation/log.h" 23 | 24 | #include "gtest/gtest.h" 25 | 26 | using namespace nvattestation; 27 | 28 | TEST(NvHttpClient, DISABLED_GetAsString) { 29 | NvHttpClient client; 30 | Error error = NvHttpClient::create(client, "", HttpOptions()); 31 | NvRequest request("https://httpbin.org/get", NvHttpMethod::HTTP_METHOD_GET); 32 | long status; 33 | std::string response; 34 | error = client.do_request_as_string(request, status, response); 35 | ASSERT_EQ(error, Error::Ok); 36 | ASSERT_EQ(status, NvHttpStatus::HTTP_STATUS_OK); 37 | ASSERT_FALSE(response.empty()); 38 | } 39 | 40 | TEST(NvHttpClient, DISABLED_GetAsStruct) { 41 | NvHttpClient client; 42 | Error error = NvHttpClient::create(client, "", HttpOptions()); 43 | NvRequest request("https://httpbin.org/get", NvHttpMethod::HTTP_METHOD_GET); 44 | long status; 45 | nlohmann::json json_response; 46 | error = client.do_request_as_json_struct(request, status, json_response); 47 | ASSERT_EQ(error, Error::Ok); 48 | ASSERT_EQ(status, NvHttpStatus::HTTP_STATUS_OK); 49 | ASSERT_FALSE(json_response.empty()); 50 | ASSERT_EQ(json_response["url"], "https://httpbin.org/get"); 51 | ASSERT_EQ(json_response["headers"]["Host"], "httpbin.org"); 52 | } 53 | 54 | TEST(NvHttpClient, DISABLED_PostAsString) { 55 | NvHttpClient client; 56 | Error error = NvHttpClient::create(client, "", HttpOptions()); 57 | NvRequest request("https://httpbin.org/post", NvHttpMethod::HTTP_METHOD_POST, {}, "{\"test\": \"test\"}"); 58 | long status; 59 | std::string response; 60 | error = client.do_request_as_string(request, status, response); 61 | ASSERT_EQ(error, Error::Ok); 62 | ASSERT_EQ(status, NvHttpStatus::HTTP_STATUS_OK); 63 | LOG_DEBUG("response: " << response); 64 | } 65 | 66 | TEST(NvHttpClient, DISABLED_PostAsStruct) { 67 | NvHttpClient client; 68 | Error error = NvHttpClient::create(client, "", HttpOptions()); 69 | NvRequest request("https://httpbin.org/post", NvHttpMethod::HTTP_METHOD_POST, {}, "{\"test\": \"test\"}"); 70 | long status; 71 | nlohmann::json json_response; 72 | error = client.do_request_as_json_struct(request, status, json_response); 73 | ASSERT_EQ(error, Error::Ok); 74 | ASSERT_EQ(status, NvHttpStatus::HTTP_STATUS_OK); 75 | ASSERT_EQ(json_response["url"], "https://httpbin.org/post"); 76 | ASSERT_EQ(json_response["headers"]["Host"], "httpbin.org"); 77 | } 78 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/scripts/lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Lint the SDK with clang-tidy. 3 | # This script can be run from any directory. 4 | # By default, it only lints changed files compared to origin/main. 5 | # Use --all to lint all files. 6 | 7 | set -euo pipefail 8 | 9 | readonly SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 10 | readonly PROJECT_DIR="$( cd "$SCRIPT_DIR/.." && pwd )" 11 | readonly BUILD_DIR="$PROJECT_DIR/build" 12 | readonly COMPILE_COMMANDS_FILE="$BUILD_DIR/compile_commands.json" 13 | 14 | # Function to get changed files 15 | get_changed_files() { 16 | local changed_files="" 17 | 18 | # Check if running in GitLab CI 19 | if [ -n "${CI:-}" ] && [ -n "${GITLAB_CI:-}" ]; then 20 | echo "Running in GitLab CI" >&2 21 | 22 | local target_branch="origin/main" 23 | 24 | # In GitLab CI, use merge request target branch if available 25 | if [ -n "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-}" ]; then 26 | target_branch="origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}" 27 | fi 28 | 29 | echo "Comparing against: $target_branch" >&2 30 | 31 | # Get changed .cpp files in src directory 32 | changed_files=$(git diff --name-only --diff-filter=ACMR --relative "$target_branch"...HEAD | grep -E '^src/.*\.cpp$' || true) 33 | else 34 | echo "Running on host machine" >&2 35 | 36 | # Get committed changes between HEAD and origin/main 37 | local committed_files=$(git diff --name-only --diff-filter=ACMR --relative origin/main...HEAD | grep -E '^src/.*\.cpp$' || true) 38 | 39 | # Get uncommitted changes 40 | local uncommitted_files=$(git diff --name-only --diff-filter=ACMR --relative HEAD | grep -E '^src/.*\.cpp$' || true) 41 | 42 | # Combine both sets of files and remove duplicates 43 | changed_files=$(echo -e "$committed_files\n$uncommitted_files" | sort -u | grep -v '^$' || true) 44 | 45 | echo "Committed changes (HEAD...origin/main): $committed_files" >&2 46 | echo "Uncommitted changes: $uncommitted_files" >&2 47 | fi 48 | 49 | echo "$changed_files" 50 | } 51 | 52 | echo "--- Linting SDK ---" 53 | cd "$PROJECT_DIR" 54 | 55 | if [ ! -f "$COMPILE_COMMANDS_FILE" ]; then 56 | echo "$COMPILE_COMMANDS_FILE not found. Build the SDK first." 57 | exit 1 58 | fi 59 | 60 | # Check if --all flag is provided 61 | if [ "${1:-}" = "--all" ]; then 62 | echo "Running on all files" 63 | source_files=$(find src -name '*.cpp') 64 | echo "Source files found: $source_files" 65 | else 66 | # Default: only lint changed files 67 | echo "Running on changed files only (use --all to lint all files)" 68 | changed_files=$(get_changed_files) 69 | 70 | if [ -z "$changed_files" ]; then 71 | echo "No .cpp files changed in src directory. Skipping clang-tidy." 72 | exit 0 73 | fi 74 | 75 | echo "Changed .cpp files found:" 76 | echo "$changed_files" 77 | source_files="$changed_files" 78 | fi 79 | 80 | # Run clang-tidy on the determined files 81 | if [ -n "$source_files" ]; then 82 | echo "Running clang-tidy on files..." 83 | clang-tidy -p="$COMPILE_COMMANDS_FILE" --quiet $source_files 84 | echo "Linting completed successfully" 85 | else 86 | echo "No source files to lint" 87 | fi -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/nv_cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "nv_attestation/error.h" 29 | 30 | namespace nvattestation { 31 | 32 | class NvCacheOptions { 33 | public: 34 | static constexpr uint64_t DEFAULT_MAX_SIZE = 1024ULL * 1024; // 1MB 35 | static constexpr time_t DEFAULT_TTL = 60 * 60; // 1 hour 36 | 37 | uint64_t max_size_bytes; 38 | time_t ttl_seconds; 39 | NvCacheOptions(uint64_t max_size, time_t ttl_seconds) : max_size_bytes(max_size), ttl_seconds(ttl_seconds) {} 40 | NvCacheOptions() : max_size_bytes(DEFAULT_MAX_SIZE), ttl_seconds(DEFAULT_TTL) {} 41 | }; 42 | 43 | class INvCache { 44 | 45 | public: 46 | virtual ~INvCache() = default; 47 | virtual Error put(const std::string& key, std::shared_ptr value, uint64_t size_bytes) = 0; 48 | virtual Error get(const std::string& key, std::shared_ptr& out_value) = 0; 49 | virtual void remove(const std::string& key) = 0; 50 | virtual void clear() = 0; 51 | }; 52 | 53 | class NvCache : public INvCache { 54 | public: 55 | // same ttl applied to all objects 56 | // o(1) get, put, remove 57 | NvCache(const std::shared_ptr& options); 58 | ~NvCache(); 59 | 60 | // T must be copyable 61 | Error put(const std::string& key, std::shared_ptr value, uint64_t size_bytes) override; 62 | Error get(const std::string& key, std::shared_ptr& out_value) override; 63 | void remove(const std::string& key) override; 64 | void clear() override; 65 | private: 66 | class NvCacheObject { 67 | public: 68 | std::shared_ptr m_value; 69 | uint64_t m_size_bytes; 70 | time_t m_expiry_time; 71 | std::list::iterator m_lru_node_ptr; 72 | std::list::iterator m_insertion_node_ptr; 73 | }; 74 | 75 | std::unordered_map m_cache; 76 | // if cache is full and no object has expired, to track which objects to evict first 77 | std::list m_lru_list; 78 | // if cache is full, to track which objects to expire first 79 | std::list m_insertion_list; 80 | 81 | uint64_t m_current_size_bytes = 0; 82 | std::mutex m_mutex; 83 | 84 | std::shared_ptr m_options; 85 | 86 | Error remove_helper(const std::string& key); 87 | }; 88 | 89 | 90 | } // namespace nvattestation -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/spdm/spdm_req.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "nv_attestation/spdm/spdm_req.hpp" 19 | #include "nv_attestation/spdm/utils.h" 20 | #include "nv_attestation/log.h" 21 | #include "nv_attestation/utils.h" 22 | 23 | namespace nvattestation { 24 | 25 | Error SpdmMeasurementRequestMessage11::create(const std::vector& request_data, SpdmMeasurementRequestMessage11& out_message) { 26 | return out_message.parse(request_data); 27 | } 28 | 29 | Error SpdmMeasurementRequestMessage11::parse(const std::vector& request_data) { 30 | if (request_data.size() != kRequestLength) { 31 | LOG_ERROR("SPDM Measurement Request Message11: Invalid request data size"); 32 | return Error::SpdmRequestParseError; 33 | } 34 | 35 | size_t offset = 0; 36 | if(!can_read_buffer(request_data, offset, kSpdmVersionSize, "SPDMVersion")) { return Error::SpdmRequestParseError; } 37 | m_spdm_version = request_data[offset]; 38 | offset += kSpdmVersionSize; 39 | 40 | if (m_spdm_version != SPDM_VERSION_1_1) { 41 | LOG_ERROR("SPDMVersion is not " << to_hex_string(SPDM_VERSION_1_1) << " (1.1). Actual version: " << to_hex_string(m_spdm_version)); 42 | return Error::SpdmRequestParseError; 43 | } 44 | 45 | if(!can_read_buffer(request_data, offset, kRequestResponseCodeSize, "RequestResponseCode")) { return Error::SpdmRequestParseError; } 46 | m_request_response_code = request_data[offset]; 47 | offset += kRequestResponseCodeSize; 48 | 49 | if (m_request_response_code != SPDM_REQ_CODE_GET_MEASUREMENTS) { 50 | LOG_ERROR("RequestResponseCode is not " << to_hex_string(SPDM_REQ_CODE_GET_MEASUREMENTS) << " (GET_MEASUREMENTS). Actual code: " << to_hex_string(m_request_response_code)); 51 | return Error::SpdmRequestParseError; 52 | } 53 | 54 | if(!can_read_buffer(request_data, offset, kParam1Size, "Param1")) { return Error::SpdmRequestParseError; } 55 | m_param1 = request_data[offset]; 56 | offset += kParam1Size; 57 | 58 | if(!can_read_buffer(request_data, offset, kParam2Size, "Param2")) { return Error::SpdmRequestParseError; } 59 | m_param2 = request_data[offset]; 60 | offset += kParam2Size; 61 | 62 | if (!checked_copy_n(m_nonce, request_data, offset, kNonceSize, "Nonce")) { 63 | return Error::SpdmRequestParseError; 64 | } 65 | offset += kNonceSize; 66 | 67 | if(!can_read_buffer(request_data, offset, kSlotIDParamSize, "SlotIDParam")) { return Error::SpdmRequestParseError; } 68 | m_slot_id_param = request_data[offset]; 69 | offset += kSlotIDParamSize; 70 | 71 | if (offset != kRequestLength) { 72 | LOG_ERROR("trailing bytes after parsing in SPDM Measurement Request Message11"); 73 | return Error::SpdmRequestParseError; 74 | } 75 | 76 | return Error::Ok; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/sample_attestation_data/hopperClaimsv3_detached_eat.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | "JWT", 4 | "eyJraWQiOiJudi1lYXQta2lkLXByb2QtMjAyNTA2MDkyMTEzMTAxMTAtOTNiMTNhYTEtMTdlNC00YzE0LTlkMzMtZGJhMjMyMzMyOWYyIiwiYWxnIjoiRVMzODQifQ.eyJzdWIiOiJOVklESUEtUExBVEZPUk0tQVRURVNUQVRJT04iLCJ4LW52aWRpYS12ZXIiOiIzLjAiLCJuYmYiOjE3NDk2MDE4NTgsImlzcyI6Imh0dHBzOi8vbnJhcy5hdHRlc3RhdGlvbi5udmlkaWEuY29tIiwieC1udmlkaWEtb3ZlcmFsbC1hdHQtcmVzdWx0Ijp0cnVlLCJzdWJtb2RzIjp7IkdQVS0wIjpbIkRJR0VTVCIsWyJTSEEtMjU2IiwiZDdjMmE5NDlhNWM2OWJmZjFhMTJkZTNkYTBjOWEyM2JjOTY2MDQxYjgxMWI5OWE4OWRmZTQ0YzJkZGU4YzM3YyJdXX0sImVhdF9ub25jZSI6IjkzMWQ4ZGQwYWRkMjAzYWMzZDhiNGZiZGU3NWUxMTUyNzhlZWZjZGNlYWM1Yjg3NjcxYTc0OGYzMjM2NGRmY2IiLCJleHAiOjE3NDk2MDU0NTgsImlhdCI6MTc0OTYwMTg1OCwianRpIjoiYjg3MmRjNGYtZWMwOS00ODE5LWExYzItNTc3ZmY2YjI0MDRjIn0.yG2ktVi_4tzpob9yOdAUsw_hYQFJzlEvc0RBKx2EGVk9EBS8s_-xFKZn8F41DUiQ43SUH7uOq7lkEAZw53uWHHsZlujBvQUdBcfSvD4YH85j0ouC6pNGML0owNoj2ixU" 5 | ], 6 | { 7 | "GPU-0": "eyJraWQiOiJudi1lYXQta2lkLXByb2QtMjAyNTA2MDkyMTEzMTAxMTAtOTNiMTNhYTEtMTdlNC00YzE0LTlkMzMtZGJhMjMyMzMyOWYyIiwiYWxnIjoiRVMzODQifQ.eyJ4LW52aWRpYS1ncHUtZHJpdmVyLXJpbS1zY2hlbWEtdmFsaWRhdGVkIjp0cnVlLCJpc3MiOiJodHRwczovL25yYXMuYXR0ZXN0YXRpb24ubnZpZGlhLmNvbSIsImVhdF9ub25jZSI6IjkzMWQ4ZGQwYWRkMjAzYWMzZDhiNGZiZGU3NWUxMTUyNzhlZWZjZGNlYWM1Yjg3NjcxYTc0OGYzMjM2NGRmY2IiLCJ4LW52aWRpYS1ncHUtdmJpb3MtcmltLXNpZ25hdHVyZS12ZXJpZmllZCI6dHJ1ZSwieC1udmlkaWEtZ3B1LXZiaW9zLXJpbS1mZXRjaGVkIjp0cnVlLCJleHAiOjE3NDk2MDU0NTgsIngtbnZpZGlhLWdwdS1kcml2ZXItcmltLXZlcnNpb24tbWF0Y2giOnRydWUsImlhdCI6MTc0OTYwMTg1OCwidWVpZCI6IjQ3ODE3NjM3OTI4NjA4MjE4NjYxODk0ODQ0NTc4NzM5MzY0NzM2NDgwMjEwNzI0OSIsImp0aSI6IjgzMzQ4MGM5LTY3OTYtNGZlNC1iNmFkLWU5YTU4ZDdhNjdiMiIsIngtbnZpZGlhLWdwdS1hdHRlc3RhdGlvbi1yZXBvcnQtbm9uY2UtbWF0Y2giOnRydWUsIngtbnZpZGlhLWdwdS12Ymlvcy1pbmRleC1uby1jb25mbGljdCI6dHJ1ZSwic2VjYm9vdCI6dHJ1ZSwieC1udmlkaWEtZ3B1LWRyaXZlci1yaW0tY2VydC1jaGFpbiI6eyJ4LW52aWRpYS1jZXJ0LXN0YXR1cyI6InZhbGlkIiwieC1udmlkaWEtY2VydC1vY3NwLXN0YXR1cyI6Imdvb2QiLCJ4LW52aWRpYS1jZXJ0LWV4cGlyYXRpb24tZGF0ZSI6IjIwMjYtMDYtMDFUMDI6MDg6MjlaIiwieC1udmlkaWEtY2VydC1yZXZvY2F0aW9uLXJlYXNvbiI6bnVsbH0sIngtbnZpZGlhLWdwdS12Ymlvcy1yaW0tY2VydC1jaGFpbiI6eyJ4LW52aWRpYS1jZXJ0LXN0YXR1cyI6InZhbGlkIiwieC1udmlkaWEtY2VydC1vY3NwLXN0YXR1cyI6Imdvb2QiLCJ4LW52aWRpYS1jZXJ0LWV4cGlyYXRpb24tZGF0ZSI6IjIwMjYtMDItMjJUMjM6MTc6NThaIiwieC1udmlkaWEtY2VydC1yZXZvY2F0aW9uLXJlYXNvbiI6bnVsbH0sIngtbnZpZGlhLWdwdS1hdHRlc3RhdGlvbi1yZXBvcnQtcGFyc2VkIjp0cnVlLCJ4LW52aWRpYS1ncHUtYXR0ZXN0YXRpb24tcmVwb3J0LWNlcnQtY2hhaW4iOnsieC1udmlkaWEtY2VydC1zdGF0dXMiOiJ2YWxpZCIsIngtbnZpZGlhLWNlcnQtb2NzcC1zdGF0dXMiOiJnb29kIiwieC1udmlkaWEtY2VydC1leHBpcmF0aW9uLWRhdGUiOiI5OTk5LTEyLTMxVDIzOjU5OjU5WiIsIngtbnZpZGlhLWNlcnQtcmV2b2NhdGlvbi1yZWFzb24iOm51bGx9LCJ4LW52aWRpYS1ncHUtZHJpdmVyLXJpbS1zaWduYXR1cmUtdmVyaWZpZWQiOnRydWUsIngtbnZpZGlhLWdwdS1hcmNoLWNoZWNrIjp0cnVlLCJ4LW52aWRpYS1ncHUtdmJpb3MtcmltLXZlcnNpb24tbWF0Y2giOnRydWUsIngtbnZpZGlhLWF0dGVzdGF0aW9uLXdhcm5pbmciOm51bGwsIm5iZiI6MTc0OTYwMTg1OCwieC1udmlkaWEtZ3B1LWRyaXZlci12ZXJzaW9uIjoiNTUwLjkwLjA3IiwieC1udmlkaWEtZ3B1LWRyaXZlci1yaW0tbWVhc3VyZW1lbnRzLWF2YWlsYWJsZSI6dHJ1ZSwieC1udmlkaWEtZ3B1LWF0dGVzdGF0aW9uLXJlcG9ydC1zaWduYXR1cmUtdmVyaWZpZWQiOnRydWUsImh3bW9kZWwiOiJHSDEwMCBBMDEgR1NQIEJST00iLCJkYmdzdGF0IjoiZGlzYWJsZWQiLCJ4LW52aWRpYS1ncHUtZHJpdmVyLXJpbS1mZXRjaGVkIjp0cnVlLCJ4LW52aWRpYS1ncHUtYXR0ZXN0YXRpb24tcmVwb3J0LWNlcnQtY2hhaW4tZndpZC1tYXRjaCI6dHJ1ZSwib2VtaWQiOiI1NzAzIiwieC1udmlkaWEtZ3B1LXZiaW9zLXJpbS1zY2hlbWEtdmFsaWRhdGVkIjp0cnVlLCJtZWFzcmVzIjoic3VjY2VzcyIsIngtbnZpZGlhLWdwdS12Ymlvcy12ZXJzaW9uIjoiOTYuMDAuOUYuMDAuMDEiLCJ4LW52aWRpYS1ncHUtdmJpb3MtcmltLW1lYXN1cmVtZW50cy1hdmFpbGFibGUiOnRydWV9.Fe3X-OGXgd0bgXNeI41gcfgjZEQKYnDxdGNEpnbi1W0CNwI7d9cFvBrZDW5aAIwmFYck9MIu5Y9bLYlFQu6CB1BsI75I15RC2Uwl0siijAeqEqSY-i1mHyJlR05SjwlL" 8 | } 9 | ] -------------------------------------------------------------------------------- /nv-attestation-cli/tests/collect_evidence_tests.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | //third party 30 | #include "gtest/gtest.h" 31 | #include 32 | 33 | //this sdk 34 | #include "collect_evidence.h" 35 | #include "nvat.h" 36 | #include "environment.h" 37 | #include "test_utils.h" 38 | #include "nvattest_options.h" 39 | 40 | TEST_F(CliTest, CollectEvidenceGPU) { //integration 41 | if (g_cli_env->test_mode != "integration" || !g_cli_env->test_device_gpu) { 42 | GTEST_SKIP() << "Skipping GPU Integration tests"; 43 | } 44 | std::string nvattest_bin = "../nvattest"; 45 | std::string cmd = nvattest_bin + " collect-evidence"; 46 | cmd += " --device gpu"; 47 | cmd += " --nonce 0x931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb"; 48 | 49 | int exit_code = 0; 50 | std::string output = exec_and_capture_output(cmd, exit_code); 51 | ASSERT_EQ(exit_code, 0) << "Command failed: " << cmd << "\nOutput:\n" << output; 52 | 53 | std::string json_str; 54 | ASSERT_TRUE(extract_json_object(output, json_str)) << "Did not find JSON in output. Raw output:\n" << output; 55 | nlohmann::json response; 56 | ASSERT_NO_THROW(response = nlohmann::json::parse(json_str)) << "Failed to parse JSON. Raw JSON:\n" << json_str; 57 | ASSERT_TRUE(response.contains("result_code")) << "JSON missing result_code. JSON:\n" << response.dump(2); 58 | EXPECT_EQ(response["result_code"].get(), 0) << "Non-zero result_code. JSON:\n" << response.dump(2); 59 | } 60 | 61 | TEST_F(CliTest, CollectEvidenceNVSwitch) { //integration 62 | if (g_cli_env->test_mode != "integration" || !g_cli_env->test_device_switch) { 63 | GTEST_SKIP() << "Skipping Switch Integration tests"; 64 | } 65 | std::string nvattest_bin = "../nvattest"; 66 | std::string cmd = nvattest_bin + " collect-evidence"; 67 | cmd += " --device nvswitch"; 68 | cmd += " --nonce 0x931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb"; 69 | 70 | int exit_code = 0; 71 | std::string output = exec_and_capture_output(cmd, exit_code); 72 | ASSERT_EQ(exit_code, 0) << "Command failed: " << cmd << "\nOutput:\n" << output; 73 | 74 | std::string json_str; 75 | ASSERT_TRUE(extract_json_object(output, json_str)) << "Did not find JSON in output. Raw output:\n" << output; 76 | nlohmann::json response; 77 | ASSERT_NO_THROW(response = nlohmann::json::parse(json_str)) << "Failed to parse JSON. Raw JSON:\n" << json_str; 78 | ASSERT_TRUE(response.contains("result_code")) << "JSON missing result_code. JSON:\n" << response.dump(2); 79 | EXPECT_EQ(response["result_code"].get(), 0) << "Non-zero result_code. JSON:\n" << response.dump(2); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/switch/claims.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "nvat.h" 21 | #include "nv_attestation/claims.h" 22 | #include 23 | 24 | namespace nvattestation { 25 | 26 | enum class SwitchClaimsVersion { 27 | V3 28 | }; 29 | 30 | std::string to_string(SwitchClaimsVersion claims_version); 31 | Error switch_claims_version_from_c(uint8_t value, SwitchClaimsVersion& out_version); 32 | 33 | class SerializableSwitchClaimsV3 : public Claims { 34 | public: 35 | std::string m_nonce; 36 | std::string m_hwmodel; 37 | std::string m_ueid; 38 | SerializableMeasresClaim m_measurements_matching; 39 | std::shared_ptr m_secure_boot; // "true" if m_measurements_matching is "success", else null 40 | std::shared_ptr m_debug_status; // "disabled" if m_measurements_matching is "success", else null 41 | std::shared_ptr> m_mismatched_measurements; // null if m_measurements_matching is "success", else the mismatched measurements 42 | 43 | bool m_switch_arch_match; // true if switch architecture is supported 44 | bool m_switch_ar_nonce_match; // true if nonce matches between switch evidence and switch attestation report 45 | std::string m_switch_bios_version; 46 | 47 | // AR claims 48 | SerializableCertChainClaims m_ar_cert_chain_claims; 49 | // if fwid is not present, this is true. if present, this is true if fwid matches with the fwid in the leaf certificate 50 | bool m_ar_cert_chain_fwid_match; 51 | bool m_ar_parsed; 52 | bool m_ar_signature_verified; 53 | 54 | // BIOS RIM claims 55 | bool m_bios_rim_fetched; 56 | SerializableCertChainClaims m_bios_rim_cert_chain; 57 | bool m_bios_rim_signature_verified; 58 | 59 | bool m_switch_bios_rim_version_match; // true if switch bios rim version matches the version in the gpu evidence 60 | 61 | bool m_bios_rim_measurements_available; 62 | 63 | std::string m_version; 64 | 65 | 66 | SerializableSwitchClaimsV3(); 67 | ~SerializableSwitchClaimsV3() override = default; 68 | Error get_nonce(std::string& out_nonce) const override; 69 | Error get_overall_result(bool& out_result) const override; 70 | Error get_version(std::string& out_version) const override; 71 | Error get_device_type(std::string& out_device_type) const override; 72 | Error serialize_json(std::string& out_string) const override; 73 | static std::vector to_cbor(); 74 | protected: 75 | nlohmann::json to_json_object() const override; 76 | }; 77 | 78 | void to_json(nlohmann::json& j, const SerializableSwitchClaimsV3& claims); 79 | void from_json(const nlohmann::json& js, SerializableSwitchClaimsV3& out_claims); 80 | 81 | 82 | bool operator==(const SerializableSwitchClaimsV3& lhs, const SerializableSwitchClaimsV3& rhs); 83 | 84 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/switch_test_utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "switch_test_utils.h" 19 | 20 | MockSwitchEvidenceData::MockSwitchEvidenceData() 21 | : architecture(SwitchArchitecture::LS10), 22 | uuid("SWITCH-11111111-2222-3333-4444-555555555555"), 23 | bios_version("96.10.55.00.01"), 24 | nonce("931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb"), 25 | attestation_report_path("testdata/switchAttestationReport.txt"), 26 | attestation_cert_chain_path("testdata/switchCertChain.txt"), 27 | tnvl_mode(true), 28 | lock_mode(true) { 29 | } 30 | 31 | // Factory method implementations for MockSwitchEvidenceData 32 | 33 | MockSwitchEvidenceData MockSwitchEvidenceData::create_default() { 34 | return MockSwitchEvidenceData(); 35 | } 36 | 37 | MockSwitchEvidenceData MockSwitchEvidenceData::create_bad_nonce_scenario() { 38 | return MockSwitchEvidenceData( 39 | SwitchArchitecture::LS10, 40 | "SWITCH-11111111-2222-3333-4444-555555555555", 41 | "96.10.55.00.01", 42 | "0000000000000000000000000000000000000000000000000000000000000000", 43 | "testdata/sample_attestation_data/switch/switchAttestationReport.txt", 44 | "testdata/sample_attestation_data/switch/switchCertChain.txt", 45 | true, 46 | true 47 | ); 48 | } 49 | 50 | MockSwitchEvidenceData MockSwitchEvidenceData::create_bad_rim_signature_scenario() { 51 | return MockSwitchEvidenceData( 52 | SwitchArchitecture::LS10, 53 | "SWITCH-11111111-2222-3333-4444-555555555555", 54 | "96.10.55.00.01", 55 | "931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb", 56 | "testdata/sample_attestation_data/switch/switchAttestationReport.txt", 57 | "testdata/sample_attestation_data/switch/switchCertChain.txt", 58 | true, 59 | true 60 | ); 61 | } 62 | 63 | MockSwitchEvidenceData MockSwitchEvidenceData::create_measurements_mismatch_scenario() { 64 | return MockSwitchEvidenceData( 65 | SwitchArchitecture::LS10, 66 | "SWITCH-11111111-2222-3333-4444-555555555555", 67 | "96.10.55.00.01", 68 | "931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb", 69 | "testdata/sample_attestation_data/switch/switchAttestationReport.txt", 70 | "testdata/sample_attestation_data/switch/switchCertChain.txt", 71 | true, 72 | true 73 | ); 74 | } 75 | 76 | MockSwitchEvidenceData MockSwitchEvidenceData::create_invalid_signature_scenario() { 77 | return MockSwitchEvidenceData( 78 | SwitchArchitecture::LS10, 79 | "SWITCH-11111111-2222-3333-4444-555555555555", 80 | "96.10.55.00.01", 81 | "EA038ED507A451E005BAE91186BC9403150A3CB8971FDEBD05FFED65EEB6A997", 82 | "testdata/sample_attestation_data/switch/switchAttestationReportInvalidSignature.txt", 83 | "testdata/sample_attestation_data/switch/switchCertChain.txt", 84 | true, 85 | true 86 | ); 87 | } 88 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Overview 4 | 5 | Define the code of conduct followed and enforced for the NVIDIA Attestation SDK. 6 | 7 | ### Intended audience 8 | 9 | Community | Developers | Project Leads 10 | 11 | ## Our Pledge 12 | 13 | In the interest of fostering an open and welcoming environment, we as 14 | contributors and maintainers pledge to making participation in our project and 15 | our community a harassment-free experience for everyone, regardless of age, body 16 | size, disability, ethnicity, sex characteristics, gender identity and expression, 17 | level of experience, education, socio-economic status, nationality, personal 18 | appearance, race, religion, or sexual identity and orientation. 19 | 20 | ## Our Standards 21 | 22 | Examples of behavior that contributes to creating a positive environment 23 | include: 24 | 25 | * Using welcoming and inclusive language 26 | * Being respectful of differing viewpoints and experiences 27 | * Gracefully accepting constructive criticism 28 | * Focusing on what is best for the community 29 | * Showing empathy towards other community members 30 | 31 | Examples of unacceptable behavior by participants include: 32 | 33 | * The use of sexualized language or imagery and unwelcome sexual attention or 34 | advances 35 | * Trolling, insulting/derogatory comments, and personal or political attacks 36 | * Public or private harassment 37 | * Publishing others' private information, such as a physical or electronic 38 | address, without explicit permission 39 | * Other conduct which could reasonably be considered inappropriate in a 40 | professional setting 41 | 42 | ## Our Responsibilities 43 | 44 | Project maintainers are responsible for clarifying the standards of acceptable 45 | behavior and are expected to take appropriate and fair corrective action in 46 | response to any instances of unacceptable behavior. 47 | 48 | Project maintainers have the right and responsibility to remove, edit, or 49 | reject comments, commits, code, wiki edits, issues, and other contributions 50 | that are not aligned to this Code of Conduct, or to ban temporarily or 51 | permanently any contributor for other behaviors that they deem inappropriate, 52 | threatening, offensive, or harmful. 53 | 54 | ## Scope 55 | 56 | This Code of Conduct applies both within project spaces and in public spaces 57 | when an individual is representing the project or its community. Examples of 58 | representing a project or community include using an official project e-mail 59 | address, posting via an official social media account, or acting as an appointed 60 | representative at an online or offline event. Representation of a project may be 61 | further defined and clarified by project maintainers. 62 | 63 | ## Enforcement 64 | 65 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 66 | reported by contacting GitHub_Conduct@nvidia.com. All complaints will be reviewed and 67 | investigated and will result in a response that is deemed necessary and appropriate 68 | to the circumstances. The project team is obligated to maintain confidentiality with 69 | regard to the reporter of an incident. Further details of specific enforcement policies 70 | may be posted separately. 71 | 72 | Project maintainers who do not follow or enforce the Code of Conduct in good 73 | faith may face temporary or permanent repercussions as determined by other 74 | members of the project's leadership. 75 | 76 | ## Attribution 77 | 78 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 79 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 80 | 81 | [homepage]: https://www.contributor-covenant.org 82 | 83 | For answers to common questions about this code of conduct, see 84 | https://www.contributor-covenant.org/faq 85 | -------------------------------------------------------------------------------- /nv-attestation-cli/src/attest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | #include 20 | #include 21 | #include 22 | 23 | #include "CLI/CLI.hpp" 24 | #include "nvat.h" 25 | #include "nvattest_options.h" 26 | 27 | namespace nvattest { 28 | 29 | /** 30 | * @brief Represents the output of the 'attest' CLI subcommand. 31 | * 32 | * Encapsulates the attestation results and provides a way to serialize it into JSON. 33 | */ 34 | class AttestOutput { 35 | public: 36 | int result_code; 37 | std::string claims; 38 | std::string detached_eat; 39 | 40 | AttestOutput(const int result_code); 41 | AttestOutput(const int result_code, const std::string& claims, const std::string& detached_eat); 42 | nlohmann::json to_json() const; 43 | }; 44 | 45 | /** 46 | * @brief Creates and adds the 'attest' subcommand to the main CLI application. 47 | * 48 | * @param app The CLI11 application to which the subcommand will be added. 49 | * @param verifier Reference to a string for verifier type, typically "local" or "remote". 50 | * @param gpu_evidence Path to a local file which contains GPU evidence. Used instead of calling NVML 51 | * @param switch_evidence Path to a local file which contains GPU evidence. Used instead of calling NSCQ 52 | * @param relying_party_policy Path to a local file which contains a Relying Party Rego policy 53 | * @param rim_url RIM Service URL 54 | * @param ocsp_url OCSP URL 55 | * @param nras_url NRAS URL 56 | * @param log_level Log level for the application 57 | * @return Pointer to the created CLI11 subcommand. 58 | */ 59 | CLI::App* create_attest_subcommand( 60 | CLI::App& app, 61 | EvidenceCollectionOptions& evidence_collection_options, 62 | EvidenceVerificationOptions& evidence_verification_options, 63 | EvidencePolicyOptions& evidence_policy_options 64 | ); 65 | 66 | /** 67 | * @brief Handles the logic when the 'attest' subcommand is invoked. 68 | * 69 | * @param device String specifying which devices to use ("gpu", "nvswitch", etc.). 70 | * @param verifier String specifying verifier type ("local" or "remote"). 71 | * @param gpu_evidence Path to a local file which contains GPU evidence. Used instead of calling NVML 72 | * @param switch_evidence Path to a local file which contains GPU evidence. Used instead of calling NSCQ 73 | * @param relying_party_policy Path to a local file which contains a Relying Party policy 74 | * @param rim_url RIM Service URL 75 | * @param ocsp_url OCSP URL 76 | * @param nras_url NRAS URL 77 | * @param log_level Log level for the application 78 | * @return Exit code for the subcommand handler (0 = success, 1 = failure, 2 = policy mismatch). 79 | */ 80 | int handle_attest_subcommand( 81 | const EvidenceCollectionOptions& evidence_collection_options, 82 | const EvidenceVerificationOptions& evidence_verification_options, 83 | const EvidencePolicyOptions& evidence_policy_options, 84 | const CommonOptions& common_options 85 | ); 86 | 87 | } 88 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/switch/verify.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "nv_attestation/switch/evidence.h" 21 | #include "nv_attestation/switch/claims.h" 22 | #include "nv_attestation/claims.h" 23 | #include "nv_attestation/error.h" 24 | #include "nv_attestation/rim.h" 25 | #include "nv_attestation/nv_x509.h" 26 | #include "nv_attestation/verify.h" 27 | 28 | namespace nvattestation { 29 | 30 | struct SwitchVerifyOptions { 31 | SwitchClaimsVersion requested_claims_version; 32 | OcspVerifyOptions ocsp_options; 33 | 34 | SwitchVerifyOptions(SwitchClaimsVersion requested_claims_version, OcspVerifyOptions ocsp_options) : requested_claims_version(requested_claims_version), ocsp_options(ocsp_options) {} 35 | SwitchVerifyOptions() : requested_claims_version(SwitchClaimsVersion::V3), ocsp_options(OcspVerifyOptions()) {} 36 | }; 37 | 38 | class ISwitchVerifier { 39 | public: 40 | virtual ~ISwitchVerifier() = default; 41 | virtual Error verify_evidence(const std::vector>& evidence, const EvidencePolicy& evidence_policy, std::string* out_detached_eat, ClaimsCollection& out_claims) = 0; 42 | }; 43 | 44 | class LocalSwitchVerifier : public ISwitchVerifier { 45 | public: 46 | static Error create(LocalSwitchVerifier& out_verifier, const std::shared_ptr& rim_store, const std::shared_ptr& ocsp_http_client, const DetachedEATOptions& detached_eat_options); 47 | Error verify_evidence(const std::vector>& evidence, const EvidencePolicy& evidence_policy, std::string* out_detached_eat, ClaimsCollection& out_claims) override; 48 | private: 49 | std::shared_ptr m_rim_store; 50 | std::shared_ptr m_ocsp_http_client; 51 | DetachedEATOptions m_detached_eat_options; 52 | 53 | Error generate_claims_v3(const std::vector>& evidence, const EvidencePolicy& evidence_policy, std::string* out_detached_eat, ClaimsCollection& out_claims) const; 54 | static Error set_switch_evidence_claims(const SwitchEvidenceClaims& switch_evidence_claims, SerializableSwitchClaimsV3& out_serializable_claims); 55 | Error set_vbios_rim_claims(const RimDocument& vbios_rim, const EvidencePolicy& evidence_policy, SerializableSwitchClaimsV3& out_serializable_claims) const ; 56 | static Error generate_set_measurement_claims(const Measurements& golden_measurements, const SwitchEvidence::AttestationReport& attestation_report, SerializableSwitchClaimsV3& out_serializable_claims); 57 | }; 58 | 59 | class NvRemoteSwitchVerifier : public ISwitchVerifier { 60 | public: 61 | static constexpr const char* DEFAULT_BASE_URL = "https://nras.attestation.nvidia.com"; 62 | 63 | static Error init_from_env(NvRemoteSwitchVerifier& out_verifier, const char* nras_url, const std::string& service_key, const HttpOptions& http_options); 64 | Error verify_evidence(const std::vector>& evidence, const EvidencePolicy& evidence_policy, std::string* out_detached_eat, ClaimsCollection& out_claims) override; 65 | private: 66 | std::string m_nras_url; 67 | std::string m_eat_issuer; 68 | NvHttpClient m_http_client; 69 | std::shared_ptr m_jwk_store; 70 | }; 71 | 72 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/claims_evaluator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include "error.h" 22 | 23 | #include "claims.h" 24 | 25 | namespace nvattestation { 26 | 27 | /** 28 | * @brief Abstract class for evaluating claims. 29 | * 30 | * This class contains functions to evaluate [Claims](@ref Claims) 31 | */ 32 | class IClaimsEvaluator { 33 | public: 34 | virtual ~IClaimsEvaluator() = default; 35 | 36 | /** 37 | * @brief Evaluates GPU_DEVICE_IDENTITY claims. 38 | * 39 | * @param claims The claims to evaluate. 40 | * @return A boolean value indicating whether the claims are valid. True if claims are valid, false 41 | * if invalid. Returns nullptr if there was an error during evaluation 42 | */ 43 | virtual Error evaluate_claims(const ClaimsCollection& claims, bool& out_match) = 0; 44 | }; 45 | 46 | 47 | /** 48 | * @brief Factory class for creating [IClaimsEvaluator](@ref IClaimsEvaluator) instances. 49 | */ 50 | class ClaimsEvaluatorFactory { 51 | public: 52 | 53 | /** 54 | * @brief Creates a claims evaluator that uses a Rego policy. 55 | * 56 | * This evaluator uses the Open Policy Agent (OPA) Rego engine to evaluate claims. When 57 | * `evaluate_gpu_claims` is called, the evaluator will use this policy to determine 58 | * whether the claims are valid. The result depends on the logic defined by the user in the policy. 59 | * 60 | * @param policy The provided `policy` must meet the following requirements: 61 | * 62 | * | Requirement | Description | 63 | * |---------------------|------------------------------------------------------------------------------------------------------| 64 | * | Package Declaration | The policy must declare the `package policy` namespace. | 65 | * | Match Rule | Must contain a rule named `nv_match` at path `policy.nv_match`. | 66 | * | Output Format | The policy must produce a boolean `nv_match` attribute at the JSON root in the evaluation result. | 67 | * 68 | * **Rule Details:** 69 | * - The `nv_match` rule determines claim validity and should return `true` or `false` based on the input. 70 | * - Rule names starting with nv_ and nvidia_ are reserved for future use. Do not create rules using these naming conventions 71 | * unless a usage is documented in the table above. 72 | * 73 | * **Example valid policy:** 74 | * ``` 75 | * package policy 76 | * default nv_match := false 77 | * nv_match := true { 78 | * input.role == "admin" 79 | * } 80 | * ``` 81 | * 82 | * **Example output:** 83 | * ``` 84 | * { "nv_match" : false } 85 | * ``` 86 | * 87 | * @return A unique pointer to a [IClaimsEvaluator](@ref IClaimsEvaluator) instance that evaluates claims using the given Rego policy. 88 | */ 89 | static std::shared_ptr create_rego_claims_evaluator(const std::string &policy); 90 | }; 91 | 92 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/integration-tests/switch_evidence_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "nv_attestation/switch/nscq_client.h" 24 | #include "nv_attestation/switch/evidence.h" 25 | 26 | using namespace nvattestation; 27 | 28 | class NscqIntegrationTest : public ::testing::Test { 29 | protected: 30 | std::string m_expected_arch; 31 | 32 | void SetUp() override { 33 | ASSERT_EQ(init_nscq(), Error::Ok); 34 | const char* env_arch = std::getenv("EXPECTED_SWITCH_ARCH"); 35 | if (env_arch == nullptr) { 36 | m_expected_arch = "LS10"; 37 | } else { 38 | m_expected_arch = env_arch; 39 | } 40 | } 41 | 42 | void TearDown() override { 43 | shutdown_nscq(); 44 | } 45 | }; 46 | 47 | TEST_F(NscqIntegrationTest, GetAllSwitchUUIDs) { 48 | std::vector uuids; 49 | Error error = get_all_switch_uuid(uuids); 50 | ASSERT_EQ(error, Error::Ok); 51 | ASSERT_FALSE(uuids.empty()); 52 | for (const auto& uuid_str : uuids) { 53 | ASSERT_FALSE(uuid_str.empty()); 54 | ASSERT_EQ(uuid_str.length(), 40); 55 | } 56 | } 57 | 58 | TEST_F(NscqIntegrationTest, GetSwitchArchitecture) { 59 | SwitchArchitecture arch; 60 | Error error = get_switch_architecture(arch); 61 | ASSERT_EQ(error, Error::Ok); 62 | 63 | std::string arch_str = to_string(arch); 64 | ASSERT_FALSE(arch_str.empty()); 65 | ASSERT_EQ(arch_str, m_expected_arch); 66 | } 67 | 68 | TEST_F(NscqIntegrationTest, SwitchEvidence) { 69 | std::vector uuids; 70 | Error error = get_all_switch_uuid(uuids); 71 | ASSERT_EQ(error, Error::Ok); 72 | if (!uuids.empty()) { 73 | std::vector nonce(NSCQ_ATTESTATION_REPORT_NONCE_SIZE, 0); 74 | for (const auto& uuid : uuids) { 75 | SwitchTnvlMode tnvl_status; 76 | error = get_switch_tnvl_status(uuid, tnvl_status); 77 | ASSERT_EQ(error, Error::Ok); 78 | 79 | std::string cert_chain; 80 | error = get_attestation_cert_chain(uuid, cert_chain); 81 | ASSERT_EQ(error, Error::Ok); 82 | ASSERT_FALSE(cert_chain.empty()); 83 | 84 | //TODO(p2): Verify the nonce 85 | std::vector report; 86 | error = get_attestation_report(uuid, nonce, report); 87 | ASSERT_EQ(error, Error::Ok); 88 | ASSERT_FALSE(report.empty()); 89 | } 90 | } 91 | } 92 | 93 | TEST_F(NscqIntegrationTest, NscqEvidenceCollectorGetEvidence) { 94 | NscqEvidenceCollector collector; 95 | std::vector nonce(NSCQ_ATTESTATION_REPORT_NONCE_SIZE, 0); 96 | std::vector> evidence_list; 97 | Error error = collector.get_evidence(nonce, evidence_list); 98 | ASSERT_EQ(error, Error::Ok); 99 | if (!evidence_list.empty()) { 100 | for (const auto& ev : evidence_list) { 101 | ASSERT_NE(ev->get_switch_architecture(), SwitchArchitecture::Unknown); 102 | ASSERT_FALSE(ev->get_uuid().empty()); 103 | ASSERT_FALSE(ev->get_attestation_report().empty()); 104 | ASSERT_FALSE(ev->get_attestation_cert_chain().empty()); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NVIDIA Attestation SDK (NVAT) 2 | 3 | [![license](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](./LICENSE) 4 | ![version](https://img.shields.io/badge/version-alpha-orange) 5 | 6 | NVAT (**NV**IDIA **At**ttestation SDK) 7 | is an open-source C++ SDK that provides resources for implementing and 8 | validating Trusted Computing Solutions on NVIDIA hardware. 9 | It focuses on attestation, a crucial aspect of ensuring the integrity and 10 | security of confidential computing environments. 11 | 12 | The core SDK is written in C++ and wrapped with a C API and CLI, 13 | with more bindings to come. 14 | 15 | ## Project Status 16 | 17 | This project is the successor of the Python-based guest tools in [nvTrust](https://github.com/NVIDIA/nvtrust), providing utilities suitable for a broader range of environments and use-cases. 18 | 19 | **Note:** This project is in **Alpha**. While we strive to minimize breaking changes, the ABI and CLI may change before stabilization. 20 | 21 | ## Components 22 | 23 | NVAT provides two components for different use cases: 24 | 25 | - **CLI (`nvattest`)**: For quick testing, scripts, and getting started. [Documentation](https://docs.nvidia.com/attestation/nv-attestation-sdk-cpp/latest/sdk-cli/introduction.html) 26 | - **C API**: For integrating attestation into C/C++ applications. [Documentation](https://docs.nvidia.com/attestation/nv-attestation-sdk-cpp/latest/sdk-c/introduction.html) 27 | 28 | ## Quick Start Guide 29 | 30 | ### Prerequisites 31 | 32 | - A supported NVIDIA GPU connected to a CVM. See [NVIDIA Trusted Computing Solutions](https://docs.nvidia.com/nvtrust/) for deployment guides covering Intel TDX and AMD SNP. 33 | - The above CVM must be running Ubuntu 22.04 or 24.04. 34 | 35 | ### Installation 36 | 37 | The steps below must be performed in a CVM connected to an NVIDIA GPU. 38 | See [Prerequisites](#prerequisites) above. 39 | 40 | 1. Install the NVIDIA Management Library (NVML). See [Driver Installation](https://docs.nvidia.com/datacenter/tesla/driver-installation-guide/index.html#ubuntu-installation-common). 41 | 42 | 2. Install the Rust compiler. See [rustup](https://www.rust-lang.org/tools/install) 43 | 44 | 3. Install additional build dependencies: 45 | ```shell 46 | apt update && \ 47 | apt install cmake git pkg-config clang \ 48 | libcurl4-openssl-dev libssl-dev libxml2-dev \ 49 | libxmlsec1-dev libxmlsec1-openssl libspdlog-dev 50 | ``` 51 | 52 | 4. Install the CLI: 53 | ```shell 54 | git clone https://github.com/NVIDIA/attestation-sdk.git 55 | cd attestation-sdk/nv-attestation-cli 56 | cmake -S . -B build -DCMAKE_BUILD_TYPE=Release 57 | cmake --build build 58 | cmake --install build 59 | sudo ldconfig 60 | ``` 61 | 62 | ### Attestation 63 | 64 | Attest the GPU(s) attached to your CVM with the following command: 65 | 66 | ```shell 67 | nvattest attest --device gpu --verifier local 68 | ``` 69 | 70 | Use `--help` to view all the options associated with the attest subcommand: 71 | 72 | ```shell 73 | nvattest attest --help 74 | ``` 75 | 76 | ### Using the C API 77 | 78 | To get started with the C API, refer to the documentation in the 79 | [SDK introduction](https://docs.nvidia.com/attestation/nv-attestation-sdk-cpp/latest/sdk-c/introduction.html). 80 | 81 | ## Documentation 82 | 83 | - [CLI introduction](https://docs.nvidia.com/attestation/nv-attestation-sdk-cpp/latest/sdk-cli/introduction.html) 84 | - [SDK introduction](https://docs.nvidia.com/attestation/nv-attestation-sdk-cpp/latest/sdk-c/introduction.html) 85 | - [NVIDIA Confidential Computing](https://docs.nvidia.com/confidential-computing/index.html) 86 | - [NVIDIA Attestation Suite](https://docs.nvidia.com/attestation) 87 | 88 | ## License 89 | 90 | This repository is licensed under Apache License v2.0 except where otherwise noted. 91 | 92 | This project will download and install additional third-party open source software projects. 93 | Review the license terms of these open source projects before use. 94 | 95 | ## Support 96 | 97 | For issues or questions, please [raise an issue on GitHub](https://github.com/NVIDIA/attestation-sdk/issues). 98 | For additional support, contact us at [attestation-support@nvidia.com](mailto:attestation-support@nvidia.com). 99 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/switchAttestationReport.txt: -------------------------------------------------------------------------------- 1 | 11e001ff931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb00116000001fa90600010133000130009083ccee6f98b6e900ea3338abde64a9ef6315d87194362d6477f911a92e19e2ef0291a19215af5f46764792ae20e08702013300013000959fb2f5c353a4b9863e67d707f9658dfe1cf68f0bfc8ffe4d1c8941c386ef8f979c2c11f90b5f5558964293f5fc631003013300013000d5a6b813360a592e3777cc3d0483d43b68b12828b19f09fc8d35b78d01000f581928b2d775ea59f830eced0032062522040133000130001f0d76a20c10f62c2ef00b052b9ab997a986d73143f4404ad64d85d9fbce27433c41ebe0c246e49d49934fb48f689e3e05013300013000ae211117e41b9e06c828e34cf094d55346683b4cd92a74f8d54af6df09fd77789e12f8245a5ed165e311597c31ccfc1f060133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000701330001300036bba147fa8d22ffa270a026bf07ef19588d544b384a685f883e752067442b7bfc150aa43d7f83d94d9ee622f7b770d80801330001300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009013300013000354ac78431b783d084a3eb871c39596b46d9da234d7dacad53c806b8759bd77ead6b7d10913266907ce75448704dd36a0a0133000130006af52fc0abb36de1bd68bf1ec24a762e6ec8888f96f6c55e1a06ddac7856de1dfae2a9b6542516da2c1fe8c5d0bcc7710b013300013000539295b7d1c181387e1ed4a0f01cc2f20e95ce38cb03da655158994b0001c44a3a80a898cc1d5d81fa9c853acae4e4980c01330001300098f6e300c4047302d2c60b9c6db9a8d64cd583509bd6eea0878d7ae7a52c44574b9f2fdf0b8781d4474463776145a05a0d0133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f013300013000b5899a3b356d72310737b93025eb8a71fa482e787e670e57646fbbadc61e391da01e64331bb9baae616d41b4afec550510013300013000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001201330001300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013013300013000463f98c21dfa57a67ead71e748c42604b84fdf2866fcdb9713220542480f3667bc2ca8c3046239321c8726d7a79e35c814013300013000e999f9fdc6a99002428b5338196ee323e1339a21c6d29bc024e981df57587e9fb60bbef517a10090096207d189ebe21e150133000130004b0b039b6841741f89872a74e28cfac569df546a002ebd52bf9051300781eb096e1f8063fda0ec37c2709ab143bbc37c16013300013000e11ae4235abedb6a554b7fb1b43f2701852405d3301ddc7dfd93fd759f4d6495fe5bf06fcd9ce5c073391b5a6e5e6dcf170133000130003ce9cc33591d7a37b933ce7d9a5a7ede118a50e813ad6042f34be16bf702f94c0b86a2c2ce5effdeda1d6c78369093af18013300013000346c1c9f239d235a1c6d69c4ff775eba92499afbdae50269aac7f7f7820b2157adea21b2814aa1b24af8ab395ac869dc190133000130007db69c2a2476ae6e2108c57c57c5d6ebe71437f60146e5ee5f99ebbf9c75f6a40b249b3701499f67a34042382968623a1a01330001300073fc1042fb63c2ef450886376f9f347036488b3722c3fb6344915cee237bcd33c4dcc818e8873863102d4a534e234b481b0133000130001a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1c0133000130001b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1d0133000130001c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1e0133000130001d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1f0133000130001e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1ef637f42290f5119391c51d861f6257bb1f151b2400dcc4701c23aa0cad6a5567200106000e0039362e31302e35352e30302e303116000800203eb31ad9ed00080c00680001000000040000000100000001000000010000000000000001000000000000006e00000001000000010000000100000000000000000000000100000000000000000000000000000001000000010000000100000001000000010000000100000001000000010000001a00800040b9c6b3d748fd90e2d85b590e713298d0f69d028e150aaa31649cf11c820858fdb529f1473cb2251043c14e835996636b811687a0a7ee7c6b811687a0a7ee7c00000101ffffffffffffffffffffffff02020300ffffffffffffffffffffffff000004010505010104040607ffffffffffffffffffffffffffffffffffffffff17000200ec001800020002001900020001003a311db0e30e04f5e0e29019c2bcf7c85642dfe0cb50956cbc0a696dced72787884fa72f9f6c13a923e42b54bd447780050b72a51ee71b8f6c1464a9de7372517ad8519eab6eedcc9b21af20c748a0a43f78a545f8e72497fdf1366896c916aa -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/sample_attestation_data/switch/switchAttestationReport.txt: -------------------------------------------------------------------------------- 1 | 11e001ff931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb00116000001fa90600010133000130009083ccee6f98b6e900ea3338abde64a9ef6315d87194362d6477f911a92e19e2ef0291a19215af5f46764792ae20e08702013300013000959fb2f5c353a4b9863e67d707f9658dfe1cf68f0bfc8ffe4d1c8941c386ef8f979c2c11f90b5f5558964293f5fc631003013300013000d5a6b813360a592e3777cc3d0483d43b68b12828b19f09fc8d35b78d01000f581928b2d775ea59f830eced0032062522040133000130001f0d76a20c10f62c2ef00b052b9ab997a986d73143f4404ad64d85d9fbce27433c41ebe0c246e49d49934fb48f689e3e05013300013000ae211117e41b9e06c828e34cf094d55346683b4cd92a74f8d54af6df09fd77789e12f8245a5ed165e311597c31ccfc1f060133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000701330001300036bba147fa8d22ffa270a026bf07ef19588d544b384a685f883e752067442b7bfc150aa43d7f83d94d9ee622f7b770d80801330001300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009013300013000354ac78431b783d084a3eb871c39596b46d9da234d7dacad53c806b8759bd77ead6b7d10913266907ce75448704dd36a0a0133000130006af52fc0abb36de1bd68bf1ec24a762e6ec8888f96f6c55e1a06ddac7856de1dfae2a9b6542516da2c1fe8c5d0bcc7710b013300013000539295b7d1c181387e1ed4a0f01cc2f20e95ce38cb03da655158994b0001c44a3a80a898cc1d5d81fa9c853acae4e4980c01330001300098f6e300c4047302d2c60b9c6db9a8d64cd583509bd6eea0878d7ae7a52c44574b9f2fdf0b8781d4474463776145a05a0d0133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f013300013000b5899a3b356d72310737b93025eb8a71fa482e787e670e57646fbbadc61e391da01e64331bb9baae616d41b4afec550510013300013000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001201330001300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013013300013000463f98c21dfa57a67ead71e748c42604b84fdf2866fcdb9713220542480f3667bc2ca8c3046239321c8726d7a79e35c814013300013000e999f9fdc6a99002428b5338196ee323e1339a21c6d29bc024e981df57587e9fb60bbef517a10090096207d189ebe21e150133000130004b0b039b6841741f89872a74e28cfac569df546a002ebd52bf9051300781eb096e1f8063fda0ec37c2709ab143bbc37c16013300013000e11ae4235abedb6a554b7fb1b43f2701852405d3301ddc7dfd93fd759f4d6495fe5bf06fcd9ce5c073391b5a6e5e6dcf170133000130003ce9cc33591d7a37b933ce7d9a5a7ede118a50e813ad6042f34be16bf702f94c0b86a2c2ce5effdeda1d6c78369093af18013300013000346c1c9f239d235a1c6d69c4ff775eba92499afbdae50269aac7f7f7820b2157adea21b2814aa1b24af8ab395ac869dc190133000130007db69c2a2476ae6e2108c57c57c5d6ebe71437f60146e5ee5f99ebbf9c75f6a40b249b3701499f67a34042382968623a1a01330001300073fc1042fb63c2ef450886376f9f347036488b3722c3fb6344915cee237bcd33c4dcc818e8873863102d4a534e234b481b0133000130001a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1c0133000130001b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1d0133000130001c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1e0133000130001d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1f0133000130001e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1ef637f42290f5119391c51d861f6257bb1f151b2400dcc4701c23aa0cad6a5567200106000e0039362e31302e35352e30302e303116000800203eb31ad9ed00080c00680001000000040000000100000001000000010000000000000001000000000000006e00000001000000010000000100000000000000000000000100000000000000000000000000000001000000010000000100000001000000010000000100000001000000010000001a00800040b9c6b3d748fd90e2d85b590e713298d0f69d028e150aaa31649cf11c820858fdb529f1473cb2251043c14e835996636b811687a0a7ee7c6b811687a0a7ee7c00000101ffffffffffffffffffffffff02020300ffffffffffffffffffffffff000004010505010104040607ffffffffffffffffffffffffffffffffffffffff17000200ec001800020002001900020001003a311db0e30e04f5e0e29019c2bcf7c85642dfe0cb50956cbc0a696dced72787884fa72f9f6c13a923e42b54bd447780050b72a51ee71b8f6c1464a9de7372517ad8519eab6eedcc9b21af20c748a0a43f78a545f8e72497fdf1366896c916aa -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/sample_attestation_data/switch/switchAttestationReportInvalidSignature.txt: -------------------------------------------------------------------------------- 1 | 11e001ffea038ed507a451e005bae91186bc9403150a3cb8971fdebd05ffed65eeb6a99700116000001fa906000101330001300039779ae98ca1d7b2e1a4ee924d54dcc8988ab690495b4e1942547b6e0fc26a6db2f55b871ccc52f5884a395607cc0914020133000130009411fd9601c74b6d2c34380669ea6f15f2ec688cf0ce0fcea14ca8f2f6d728cf73657ebd33a95bcf93573d0f25e6e02f03013300013000d5a6b813360a592e3777cc3d0483d43b68b12828b19f09fc8d35b78d01000f581928b2d775ea59f830eced0032062522040133000130001f0d76a20c10f62c2ef00b052b9ab997a986d73143f4404ad64d85d9fbce27433c41ebe0c246e49d49934fb48f689e3e05013300013000f4c00bcbdfdc20490349b1757578ffacfc59c5c60756e02fbbd1eba22760e7757ee5b7a300c98628ae069608a61bf32106013300013000d9771a9966810d478a8ff307182c56d8d7aa3c8b6f82b530078d9fe7b9488469440d153f15539debdf44d7579853a85007013300013000546cf18f4305f39fd8d18a345635de1ec828825db542460749d035f7227ad49da81e9f9d9c72856719c4d204c837bb4908013300013000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090133000130000c69190d62751af08ea082ad6cc015277f0e31cba6148fcb68c54da5b0d934d9ffb2781082520c55f10f1d7e2b3809910a0133000130006af52fc0abb36de1bd68bf1ec24a762e6ec8888f96f6c55e1a06ddac7856de1dfae2a9b6542516da2c1fe8c5d0bcc7710b013300013000215ddeca34107e683e0f5604f2b830d02707239633e7e1532d455f9167b09d2db0b95c85b4a48ed661607c6dd7fbbd6e0c013300013000215ddeca34107e683e0f5604f2b830d02707239633e7e1532d455f9167b09d2db0b95c85b4a48ed661607c6dd7fbbd6e0d0133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f013300013000215ddeca34107e683e0f5604f2b830d02707239633e7e1532d455f9167b09d2db0b95c85b4a48ed661607c6dd7fbbd6e10013300013000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110133000130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001201330001300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013013300013000dd23e00b9b49c453f76ba7b4593e1c711322fe7c0968ffa4c57ddb92657e736382b3f055f2caf9ef80f5c2c09c74098414013300013000ce3130c2b442178f3bbf3ee1b38c7a493a5bf5383b1d79a94c5efd26071a2b46fa644b4ecccc8776cf2a09131849df6d15013300013000dd23e00b9b49c453f76ba7b4593e1c711322fe7c0968ffa4c57ddb92657e736382b3f055f2caf9ef80f5c2c09c74098416013300013000ce3130c2b442178f3bbf3ee1b38c7a493a5bf5383b1d79a94c5efd26071a2b46fa644b4ecccc8776cf2a09131849df6d170133000130006a18e74c49f8f7219f18bacd5a644fe1d70ce8bae7d0719a1b8762f3312d9b3a5bf944b231c061db639cffc453949585180133000130004e772298f82ed74542e0b4661642431f987ee98f843c39ae54fa14f155e8473d78adeecd7246d8fdcf33eee472dca58e190133000130006a18e74c49f8f7219f18bacd5a644fe1d70ce8bae7d0719a1b8762f3312d9b3a5bf944b231c061db639cffc4539495851a0133000130004e772298f82ed74542e0b4661642431f987ee98f843c39ae54fa14f155e8473d78adeecd7246d8fdcf33eee472dca58e1b0133000130001a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1c0133000130001b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1d0133000130001c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1e0133000130001d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1f0133000130001e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e8df873d93463308101685234df14c3eefbc5366772e8e389fa7a727f5e1736bf200106000e0039362e31302e35322e30302e303016000800c3bb8fd8376414ca0c00680001000000040000000100000001000000010000000100000001000000000000006e000000010000000100000001000000000000000000000001000000000000000000000000000000010000000100000001000000010000000100000001000000010000000100000004008000a518059085e211d428af33e99aafe83959db9667bc503472b5736682698ba5b925868ae20338cde061b720d7e3f020dfb3806c71ed35974721aa049605b5e906ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000001010000010102020303020203030404050504040505060607070606070717000200ec0018000200000019000200010032966017caeeea825971900ea911162b6e0fced61ff9e26d21d445d75d34af34e89d6f075a8bb8717e2e51f8eeee5e9ac48ee0811031ea77841bb643ee0a6546e521bf30e60ca34c849024a1658f6c00ba3d821ddad16fccf983acd83a375c39 -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/internal/rego_engine/regorus.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #ifndef REGORUS_WRAPPER_HPP 19 | #define REGORUS_WRAPPER_HPP 20 | 21 | #include 22 | #include 23 | 24 | #include "regorus.ffi.hpp" 25 | 26 | namespace regorus { 27 | 28 | class Result { 29 | public: 30 | 31 | operator bool() const { return result.status == RegorusStatus::RegorusStatusOk; } 32 | bool operator !() const { return result.status != RegorusStatus::RegorusStatusOk; } 33 | 34 | const char* output() const { 35 | if (*this && result.output != nullptr) { 36 | return result.output; 37 | } 38 | return ""; 39 | } 40 | 41 | const char* error() const { 42 | if (!*this && result.error_message != nullptr) { 43 | return result.error_message; 44 | } 45 | return ""; 46 | } 47 | 48 | ~Result() { 49 | regorus_result_drop(result); 50 | } 51 | 52 | // Move constructor that avoids the "from" object from deallocating the same handles 53 | Result(Result&& other) noexcept : result(other.result) { 54 | other.result.output = nullptr; 55 | other.result.error_message = nullptr; 56 | other.result.status = RegorusStatus::RegorusStatusError; 57 | } 58 | 59 | private: 60 | friend class Engine; 61 | RegorusResult result; 62 | Result(RegorusResult result) : result(result) {} 63 | Result(const Result&) = delete; 64 | }; 65 | 66 | class Engine { 67 | public: 68 | Engine() : Engine(regorus_engine_new()) {} 69 | 70 | std::unique_ptr clone() const { 71 | return std::unique_ptr(new Engine(regorus_engine_clone(engine))); 72 | } 73 | 74 | Result set_rego_v0(bool enable) { 75 | return Result(regorus_engine_set_rego_v0(engine, enable)); 76 | } 77 | 78 | Result add_policy(const char* path, const char* policy) { 79 | return Result(regorus_engine_add_policy(engine, path, policy)); 80 | } 81 | 82 | Result add_policy_from_file(const char* path) { 83 | return Result(regorus_engine_add_policy_from_file(engine, path)); 84 | } 85 | 86 | Result add_data_json(const char* data) { 87 | return Result(regorus_engine_add_data_json(engine, data)); 88 | } 89 | 90 | Result add_data_from_json_file(const char* path) { 91 | return Result(regorus_engine_add_data_from_json_file(engine, path)); 92 | } 93 | 94 | Result set_input_json(const char* input) { 95 | return Result(regorus_engine_set_input_json(engine, input)); 96 | } 97 | 98 | Result set_input_from_json_file(const char* path) { 99 | return Result(regorus_engine_set_input_from_json_file(engine, path)); 100 | } 101 | 102 | Result eval_query(const char* query) { 103 | return Result(regorus_engine_eval_query(engine, query)); 104 | } 105 | 106 | Result eval_rule(const char* rule) { 107 | return Result(regorus_engine_eval_rule(engine, rule)); 108 | } 109 | 110 | Result set_enable_coverage(bool enable) { 111 | return Result(regorus_engine_set_enable_coverage(engine, enable)); 112 | } 113 | 114 | Result clear_coverage_data() { 115 | return Result(regorus_engine_clear_coverage_data(engine)); 116 | } 117 | 118 | Result get_coverage_report() { 119 | return Result(regorus_engine_get_coverage_report(engine)); 120 | } 121 | 122 | Result get_coverage_report_pretty() { 123 | return Result(regorus_engine_get_coverage_report_pretty(engine)); 124 | } 125 | 126 | ~Engine() { 127 | regorus_engine_drop(engine); 128 | } 129 | 130 | private: 131 | RegorusEngine *engine; 132 | Engine(RegorusEngine *engine) : engine(engine) {} 133 | Engine(const Engine &) = delete; 134 | Engine(Engine &&) = delete; 135 | Engine &operator=(const Engine &) = delete; 136 | }; 137 | } 138 | 139 | #endif // REGORUS_WRAPPER_HPP -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/examples/custom-logger/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | 22 | 23 | nvat_rc_t run(void); 24 | 25 | int main(void) { 26 | nvat_rc_t rc = run(); 27 | nvat_sdk_shutdown(); 28 | if (rc != NVAT_RC_OK) { 29 | fprintf(stderr, "custom-logger failed: %s (nvat code: %03d)\n", nvat_rc_to_string(rc), rc); 30 | return 1; 31 | } 32 | return 0; 33 | } 34 | 35 | // Custom callback to determine whether a log message should be processed 36 | bool should_log_cb(nvat_log_level_t level, const char* filename, const char* function, int line_number, void* user_data) { 37 | // Allow all messages at TRACE level and above 38 | return level >= NVAT_LOG_LEVEL_TRACE; 39 | } 40 | 41 | // Custom callback to handle log messages 42 | void log_cb(nvat_log_level_t level, const char* message, const char* filename, const char* function, int line_number, void* user_data) { 43 | char* level_str = ""; 44 | if (level == NVAT_LOG_LEVEL_ERROR) { 45 | level_str = " [ERROR]"; 46 | } 47 | // Format: [user_data] [filename:line function][LEVEL]: message 48 | fprintf(stdout, "[%s] [%s:%d %s]%s: %s\n", (char*) user_data, filename, line_number, function, level_str, message); 49 | } 50 | 51 | // Custom callback for flushing buffered log messages 52 | void flush_cb(void* user_data) { 53 | fprintf(stdout, "invoked flush() on custom logger\n"); 54 | } 55 | 56 | nvat_rc_t run(void) { 57 | // Step 1: Create SDK options 58 | nvat_sdk_opts_t opts; 59 | nvat_rc_t err = nvat_sdk_opts_create(&opts); 60 | if (err != NVAT_RC_OK) { 61 | return err; 62 | } 63 | 64 | // Step 2: Create custom logger with callbacks 65 | // Define three callback functions: 66 | // - should_log_cb: Filters messages based on log level, filename, function, and line number 67 | // - log_cb: Handles the actual log message formatting and output 68 | // - flush_cb: Handles requests to flush any buffered log messages 69 | // nvat_logger_callback_create creates a custom logger backend with your callback functions 70 | // The user_data parameter allows passing custom context to all callbacks 71 | nvat_logger_t logger; 72 | err = nvat_logger_callback_create( 73 | &logger, 74 | log_cb, // Log message callback 75 | should_log_cb, // Log filtering callback 76 | flush_cb, // Flush callback 77 | "custom-logger-data" // User data passed to callbacks 78 | ); 79 | if (err != NVAT_RC_OK) { 80 | return err; 81 | } 82 | // Step 3: Set the custom logger in SDK options 83 | // nvat_sdk_opts_set_logger connects your custom logger to the SDK options 84 | // The logger becomes active when nvat_sdk_init is called 85 | nvat_sdk_opts_set_logger(opts, logger); 86 | 87 | // Step 4: Initialize SDK with custom logger 88 | err = nvat_sdk_init(opts); 89 | if (err != NVAT_RC_OK) { 90 | nvat_sdk_opts_free(&opts); 91 | nvat_logger_free(&logger); 92 | return err; 93 | } 94 | 95 | // Step 5: Trigger a log message (intentional error for demonstration) 96 | // When the SDK generates log messages, your callbacks are invoked: 97 | // - should_log_cb first determines if the message should be processed 98 | // - If allowed, log_cb handles formatting and output 99 | // - flush_cb is called when buffered messages should be flushed 100 | // The example intentionally triggers an error message by passing NULL to a function 101 | // that requires a valid pointer, demonstrating how SDK errors are logged through your custom system 102 | nvat_http_options_create_default(NULL); 103 | 104 | return NVAT_RC_OK; 105 | } 106 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/spdm/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include // For std::stringstream 24 | #include 25 | #include "nv_attestation/log.h" // For LOG_PUSH_ERROR 26 | #include "nv_attestation/error.h" // For Error enum 27 | #include "nv_attestation/utils.h" 28 | 29 | namespace nvattestation { 30 | 31 | constexpr uint8_t SPDM_VERSION_1_1 = 0x11; 32 | constexpr uint8_t SPDM_REQ_CODE_GET_MEASUREMENTS = 0xe0; 33 | constexpr uint8_t SPDM_RES_CODE_MEASUREMENTS = 0x60; 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | /** 44 | * @brief Assigns a range from one vector to another, checking for integer overflows. 45 | * @param target The target vector to assign to. 46 | * @param source The source vector to assign from. 47 | * @param u_offset The starting offset in the source vector. 48 | * @param u_length The number of bytes to assign from the source vector. 49 | * @param field_name The name of the field being parsed, for logging purposes. 50 | * @return true if the assignment was successful, false otherwise. 51 | */ 52 | static bool checked_assign( 53 | std::vector &target, 54 | const std::vector &source, 55 | size_t u_offset, 56 | size_t u_length, 57 | const char* field_name) { 58 | if (!can_read_buffer(source, u_offset, u_length, field_name)) { 59 | return false; 60 | } 61 | std::vector::difference_type offset = 62 | static_cast::difference_type>(u_offset); 63 | if (offset < 0) { 64 | LOG_ERROR("Detected integer overflow calculating offset for: " << field_name); 65 | return false; 66 | } 67 | std::vector::difference_type length = 68 | static_cast::difference_type>(u_length); 69 | if (length < 0) { 70 | LOG_ERROR("Detected integer overflow calculating length for: " << field_name); 71 | return false; 72 | } 73 | target.assign(source.begin() + offset, source.begin() + offset + length); 74 | return true; 75 | } 76 | 77 | /** 78 | * @brief Copies a range from a vector to an array, checking for integer overflows. 79 | * @param target The target array to copy to. 80 | * @param source The source vector to copy from. 81 | * @param u_offset The starting offset in the source vector. 82 | * @param u_length The number of bytes to copy from the source vector. 83 | * @param field_name The name of the field being parsed, for logging purposes. 84 | * @return true if the copy was successful, false otherwise. 85 | */ 86 | template 87 | static bool checked_copy_n( 88 | std::array &target, 89 | const std::vector &source, 90 | size_t u_offset, 91 | size_t u_length, 92 | const char* field_name) { 93 | if (u_length > N) { 94 | LOG_ERROR("Array too small for: " << field_name); 95 | return false; 96 | } 97 | if (!can_read_buffer(source, u_offset, u_length, field_name)) { 98 | return false; 99 | } 100 | std::vector::difference_type offset = 101 | static_cast::difference_type>(u_offset); 102 | if (offset < 0) { 103 | LOG_ERROR("Detected integer overflow calculating offset for: " << field_name); 104 | return false; 105 | } 106 | std::vector::difference_type length = 107 | static_cast::difference_type>(u_length); 108 | if (length < 0) { 109 | LOG_ERROR("Detected integer overflow calculating length for: " << field_name); 110 | return false; 111 | } 112 | std::copy_n(source.begin() + offset, length, target.data()); 113 | return true; 114 | } 115 | } // namespace nvattestation 116 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/src/nv_cache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "nv_attestation/nv_cache.h" 23 | #include "nv_attestation/error.h" 24 | #include "nv_attestation/log.h" 25 | 26 | namespace nvattestation { 27 | 28 | NvCache::NvCache(const std::shared_ptr& options) { 29 | if (options == nullptr) { 30 | m_options = std::make_shared(); 31 | } else { 32 | m_options = options; 33 | } 34 | } 35 | 36 | Error NvCache::put(const std::string& key, std::shared_ptr value, uint64_t size_bytes) { 37 | if (size_bytes > m_options->max_size_bytes) { 38 | LOG_ERROR("A single object with key "<< key << " and size " << size_bytes << " is too large to fit in the cache"); 39 | LOG_ERROR("Cache size: " << m_current_size_bytes << " bytes"); 40 | return Error::BadArgument; 41 | } 42 | 43 | std::lock_guard lock(m_mutex); 44 | 45 | if (m_cache.find(key) != m_cache.end()) { 46 | remove_helper(key); 47 | } 48 | 49 | while(!m_insertion_list.empty() && m_current_size_bytes + size_bytes > m_options->max_size_bytes) { 50 | std::string oldest_key = m_insertion_list.back(); 51 | if (m_cache[oldest_key].m_expiry_time > time(nullptr)) { 52 | break; 53 | } 54 | remove_helper(oldest_key); 55 | } 56 | 57 | while(!m_lru_list.empty() && m_current_size_bytes + size_bytes > m_options->max_size_bytes) { 58 | std::string oldest_key = m_lru_list.back(); 59 | remove_helper(oldest_key); 60 | } 61 | 62 | m_current_size_bytes += size_bytes; 63 | m_lru_list.push_front(key); 64 | m_insertion_list.push_front(key); 65 | 66 | m_cache[key] = NvCacheObject{ 67 | value, 68 | size_bytes, 69 | time(nullptr) + m_options->ttl_seconds, 70 | m_lru_list.begin(), 71 | m_insertion_list.begin(), 72 | }; 73 | return Error::Ok; 74 | } 75 | 76 | Error NvCache::get(const std::string& key, std::shared_ptr& out_value) { 77 | std::lock_guard lock(m_mutex); 78 | if (m_cache.find(key) == m_cache.end()) { 79 | LOG_DEBUG("Cache object not found for key: " << key); 80 | return Error::CacheObjectNotFound; 81 | } 82 | if (m_cache[key].m_expiry_time <= time(nullptr)) { 83 | LOG_DEBUG("Cache object expired for key: " << key); 84 | return Error::CacheObjectNotFound; 85 | } 86 | out_value = m_cache[key].m_value; 87 | 88 | m_lru_list.splice(m_lru_list.begin(), m_lru_list, m_cache[key].m_lru_node_ptr); 89 | 90 | return Error::Ok; 91 | } 92 | 93 | void NvCache::remove(const std::string& key) { 94 | std::lock_guard lock(m_mutex); 95 | if (m_cache.find(key) == m_cache.end()) { 96 | LOG_DEBUG("Cache object not found for key: " << key); 97 | return; 98 | } 99 | m_current_size_bytes -= m_cache[key].m_size_bytes; 100 | m_lru_list.erase(m_cache[key].m_lru_node_ptr); 101 | m_insertion_list.erase(m_cache[key].m_insertion_node_ptr); 102 | m_cache.erase(key); 103 | } 104 | 105 | Error NvCache::remove_helper(const std::string& key) { 106 | m_current_size_bytes -= m_cache[key].m_size_bytes; 107 | m_lru_list.erase(m_cache[key].m_lru_node_ptr); 108 | m_insertion_list.erase(m_cache[key].m_insertion_node_ptr); 109 | m_cache.erase(key); 110 | return Error::Ok; 111 | } 112 | 113 | void NvCache::clear() { 114 | std::lock_guard lock(m_mutex); 115 | m_cache.clear(); 116 | m_lru_list.clear(); 117 | m_insertion_list.clear(); 118 | m_current_size_bytes = 0; 119 | } 120 | 121 | NvCache::~NvCache() { 122 | } 123 | 124 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/attestation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "claims_evaluator.h" 26 | #include "nv_attestation/claims.h" 27 | #include "nv_attestation/nv_x509.h" 28 | #include "nv_attestation/verify.h" 29 | #include "rim.h" 30 | #include "log.h" 31 | #include "gpu/evidence.h" 32 | #include "nv_http.h" 33 | #include "nv_attestation/utils.h" 34 | #include "nv_attestation/gpu/verify.h" 35 | #include "nv_attestation/switch/evidence.h" 36 | #include "nv_attestation/switch/verify.h" 37 | 38 | using namespace std; 39 | 40 | namespace nvattestation { 41 | 42 | using Nonce = vector; // TODO(p2): find better place to declare these 43 | 44 | class AttestationContext { 45 | private: 46 | VerifierType m_default_verifier_type = VerifierType::Remote; 47 | HttpOptions m_default_http_options; 48 | shared_ptr m_default_ocsp_client = nullptr; 49 | std::string m_default_ocsp_url = ""; 50 | shared_ptr m_default_rim_store = nullptr; 51 | std::string m_default_rim_store_url = ""; 52 | 53 | bool m_gpu_enabled; 54 | shared_ptr m_gpu_evidence_source = nullptr; 55 | shared_ptr m_gpu_verifier = nullptr; 56 | 57 | bool m_switch_enabled; 58 | shared_ptr m_switch_evidence_source = nullptr; 59 | shared_ptr m_switch_verifier = nullptr; 60 | std::string m_default_nras_url = ""; 61 | 62 | EvidencePolicy m_evidence_policy; 63 | shared_ptr m_claims_evaluator = nullptr; 64 | 65 | DetachedEATOptions m_eat_options; 66 | 67 | std::string m_service_key = ""; 68 | 69 | Error ensure_init(); 70 | Error attest_gpus(Nonce& nonce, std::string* out_detached_eat, ClaimsCollection& out_claims); 71 | Error attest_switches(Nonce& nonce, std::string* out_detached_eat, ClaimsCollection& out_claims); 72 | 73 | public: 74 | AttestationContext() : 75 | m_default_verifier_type(VerifierType::Remote), 76 | m_default_http_options(HttpOptions{}), 77 | m_gpu_enabled(true), 78 | m_gpu_verifier(nullptr), 79 | m_switch_enabled(false), 80 | m_evidence_policy(EvidencePolicy()), 81 | m_claims_evaluator(nullptr), 82 | m_eat_options(DetachedEATOptions()) {} 83 | 84 | ~AttestationContext() = default; 85 | 86 | void set_verifier_type(VerifierType verifier_type); 87 | void set_device_type(nvat_devices_t device_type); 88 | void set_default_http_options(HttpOptions); 89 | void set_default_rim_store_url(const char* rim_store_url); 90 | void set_default_ocsp_url(const char* ocsp_url); 91 | void set_default_nras_url(const char* nras_url); 92 | void set_default_rim_store(shared_ptr rim_store); 93 | void set_default_ocsp_client(shared_ptr ocsp_client); 94 | void set_evidence_policy(EvidencePolicy policy); 95 | void set_claims_evaluator(shared_ptr claims_evaluator); 96 | void set_gpu_evidence_source(shared_ptr evidence_source); 97 | void set_switch_evidence_source(shared_ptr evidence_source); 98 | Error set_gpu_evidence_source_json_file(const std::string& file_path); 99 | Error set_switch_evidence_source_json_file(const std::string& file_path); 100 | void set_gpu_verifier(shared_ptr verifier); 101 | void set_switch_verifier(shared_ptr verifier); 102 | void set_detached_eat_options(const DetachedEATOptions& options); 103 | void set_service_key(const std::string& service_key); 104 | 105 | Error attest_device( 106 | Nonce nonce, 107 | std::string* out_detached_eat, 108 | ClaimsCollection& out_claims 109 | ); 110 | }; 111 | } 112 | -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/gpu/claims.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | #include 20 | #include 21 | #include 22 | 23 | #include "nvat.h" 24 | #include "nv_attestation/claims.h" 25 | #include "nv_attestation/error.h" 26 | 27 | namespace nvattestation { 28 | 29 | 30 | enum class GpuClaimsVersion { 31 | V2, 32 | V3, 33 | }; 34 | 35 | std::string to_string(GpuClaimsVersion version); 36 | Error gpu_claims_version_from_c(uint8_t value, GpuClaimsVersion& out_version); 37 | 38 | class SerializableGpuClaimsV3 : public Claims { 39 | public: 40 | std::string m_nonce; 41 | std::string m_hwmodel; 42 | std::string m_ueid; 43 | std::string m_oem_id; 44 | 45 | std::string m_driver_version; 46 | std::string m_vbios_version; 47 | 48 | // Top-level measurement claims 49 | SerializableMeasresClaim m_measurements_matching; 50 | bool m_gpu_arch_match; 51 | std::shared_ptr m_secure_boot; // "true" if m_measurements_matching is "success", else null 52 | std::shared_ptr m_debug_status; // "disabled" if m_measurements_matching is "success", else null 53 | std::shared_ptr> m_mismatched_measurements; // null if m_measurements_matching is "success", else the mismatched measurements 54 | 55 | 56 | // Attestation report certificate chain claims 57 | SerializableCertChainClaims m_ar_cert_chain; 58 | bool m_ar_cert_chain_fwid_match; 59 | bool m_ar_parsed; 60 | bool m_gpu_ar_nonce_match; 61 | bool m_ar_signature_verified; 62 | 63 | // Driver RIM claims 64 | bool m_driver_rim_fetched; 65 | SerializableCertChainClaims m_driver_rim_cert_chain; 66 | bool m_driver_rim_signature_verified; 67 | bool m_gpu_driver_rim_version_match; 68 | bool m_driver_rim_measurements_available; 69 | 70 | // VBIOS RIM claims 71 | bool m_vbios_rim_fetched; 72 | SerializableCertChainClaims m_vbios_rim_cert_chain; 73 | bool m_gpu_vbios_rim_version_match; 74 | bool m_vbios_rim_signature_verified; 75 | bool m_vbios_rim_measurements_available; 76 | bool m_vbios_index_no_conflict; 77 | 78 | std::string m_mode; 79 | std::string m_version; 80 | 81 | 82 | 83 | /** 84 | * @brief Constructs a GpuClaims object with default values. 85 | * 86 | * Initializes all claims to false. 87 | */ 88 | SerializableGpuClaimsV3(); 89 | 90 | /** 91 | * @brief Destructor 92 | */ 93 | ~SerializableGpuClaimsV3() override = default; 94 | 95 | /** 96 | * @brief Serializes the GpuClaims as JSON 97 | * @return JSON string with the exact structure matching the Python implementation 98 | */ 99 | Error serialize_json(std::string& out_string) const override; 100 | 101 | Error get_nonce(std::string& out_nonce) const override; 102 | Error get_overall_result(bool& out_result) const override; 103 | Error get_version(std::string& out_version) const override; 104 | Error get_device_type(std::string& out_device_type) const override; 105 | 106 | /** 107 | * @brief Serializes the GpuClaims as CBOR 108 | * @return CBOR bytes 109 | */ 110 | std::vector to_cbor() const; 111 | 112 | protected: 113 | nlohmann::json to_json_object() const override; 114 | }; 115 | void from_json(const nlohmann::json& j, SerializableGpuClaimsV3& out_claims); 116 | void to_json(nlohmann::json& j, const SerializableGpuClaimsV3& claims); 117 | 118 | /** 119 | * @brief Operator== for SerializableGpuClaimsV3 120 | * @param lhs Left-hand side SerializableGpuClaimsV3 object 121 | * @param rhs Right-hand side SerializableGpuClaimsV3 object 122 | * @return true if objects are equal, false otherwise 123 | */ 124 | bool operator==(const SerializableGpuClaimsV3& lhs, const SerializableGpuClaimsV3& rhs); 125 | } -------------------------------------------------------------------------------- /nv-attestation-cli/src/nvattest_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include "nvat.h" 22 | 23 | namespace nvattest { 24 | 25 | template struct DeleterOf; 26 | 27 | template<> struct DeleterOf { 28 | void operator()(nvat_attestation_ctx_t* ptr) const { 29 | if (ptr) { 30 | nvat_attestation_ctx_free(ptr); 31 | } 32 | } 33 | }; 34 | 35 | template<> struct DeleterOf { 36 | void operator()(nvat_relying_party_policy_t* ptr) const { 37 | if (ptr) { 38 | nvat_relying_party_policy_free(ptr); 39 | } 40 | } 41 | }; 42 | 43 | template<> struct DeleterOf { 44 | void operator()(nvat_sdk_opts_t* ptr) const { 45 | if (ptr) { 46 | nvat_sdk_opts_free(ptr); 47 | } 48 | } 49 | }; 50 | 51 | template<> struct DeleterOf { 52 | void operator()(nvat_claims_collection_t* ptr) const { 53 | if (ptr) { 54 | nvat_claims_collection_free(ptr); 55 | } 56 | } 57 | }; 58 | 59 | template<> struct DeleterOf { 60 | void operator()(nvat_rim_store_t* ptr) const { 61 | if (ptr) { 62 | nvat_rim_store_free(ptr); 63 | } 64 | } 65 | }; 66 | 67 | template<> struct DeleterOf { 68 | void operator()(nvat_ocsp_client_t* ptr) const { 69 | if (ptr) { 70 | nvat_ocsp_client_free(ptr); 71 | } 72 | } 73 | }; 74 | 75 | template<> struct DeleterOf { 76 | using pointer = nvat_evidence_policy_t; 77 | void operator()(nvat_evidence_policy_t ptr) const { 78 | if (ptr) { 79 | nvat_evidence_policy_free(&ptr); 80 | } 81 | } 82 | }; 83 | 84 | template<> struct DeleterOf { 85 | void operator()(nvat_gpu_evidence_source_t* ptr) const { 86 | if (ptr) { 87 | nvat_gpu_evidence_source_free(ptr); 88 | } 89 | } 90 | }; 91 | 92 | template<> struct DeleterOf { 93 | void operator()(nvat_nonce_t* ptr) const { 94 | if (ptr) { 95 | nvat_nonce_free(ptr); 96 | } 97 | } 98 | }; 99 | 100 | template<> struct DeleterOf { 101 | void operator()(nvat_str_t* ptr) const { 102 | if (ptr) { 103 | nvat_str_free(ptr); 104 | } 105 | } 106 | }; 107 | 108 | template<> struct DeleterOf { 109 | void operator()(nvat_switch_evidence_source_t* ptr) const { 110 | if (ptr) { 111 | nvat_switch_evidence_source_free(ptr); 112 | } 113 | } 114 | }; 115 | 116 | class GpuEvidenceWrapper { 117 | public: 118 | nvat_gpu_evidence_t* evidences = nullptr; 119 | size_t num_evidences = 0; 120 | }; 121 | 122 | template<> struct DeleterOf { 123 | void operator()(GpuEvidenceWrapper* ptr) const { 124 | if (ptr && ptr->evidences) { 125 | nvat_gpu_evidence_array_free(&ptr->evidences, ptr->num_evidences); 126 | } 127 | delete ptr; 128 | } 129 | }; 130 | 131 | class SwitchEvidenceWrapper { 132 | public: 133 | nvat_switch_evidence_t* evidences = nullptr; 134 | size_t num_evidences = 0; 135 | }; 136 | 137 | template<> struct DeleterOf { 138 | void operator()(SwitchEvidenceWrapper* ptr) const { 139 | if (ptr && ptr->evidences) { 140 | nvat_switch_evidence_array_free(&ptr->evidences, ptr->num_evidences); 141 | } 142 | delete ptr; 143 | } 144 | }; 145 | 146 | template using nv_unique_ptr = std::unique_ptr>; 147 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(nv-attestation-unit-tests) 3 | 4 | find_package(GTest REQUIRED) 5 | 6 | option(SANITIZER "Select a sanitizer" OFF) 7 | 8 | add_executable(nv-attestation-unit-tests 9 | main.cpp 10 | rim_test.cpp 11 | rego_engine/regorus_rego_engine_test.cpp 12 | attestation_test.cpp 13 | claims_evaluator_test.cpp 14 | gpu/spdm/spdm_req_test.cpp 15 | gpu/spdm/spdm_resp_test.cpp 16 | nv_x509_test.cpp 17 | error_test.cpp 18 | gpu/evidence_test.cpp 19 | gpu/claims_test.cpp 20 | gpu/verifier_test.cpp 21 | test_utils.cpp 22 | utils_test.cpp 23 | spdm_test_utils.cpp 24 | switch/spdm/spdm_req_test.cpp 25 | switch/spdm/spdm_resp_test.cpp 26 | switch/evidence_test.cpp 27 | switch/verifier_test.cpp 28 | switch_test_utils.cpp 29 | nv_http_test.cpp 30 | claims_test.cpp 31 | nv_cache_test.cpp 32 | ) 33 | 34 | target_include_directories(nv-attestation-unit-tests PRIVATE 35 | nv-attestation 36 | ${regorus_SOURCE_DIR}/bindings/ffi 37 | ${CMAKE_CURRENT_SOURCE_DIR}/include 38 | ) 39 | 40 | target_compile_options(nv-attestation-unit-tests PRIVATE -Wno-unused -Wno-c++17-attribute-extensions) 41 | if (SANITIZER) 42 | target_compile_options(nv-attestation-unit-tests PRIVATE -fsanitize=${SANITIZER} -fno-sanitize-recover=all) 43 | target_link_options(nv-attestation-unit-tests PRIVATE -fsanitize=${SANITIZER} -fno-sanitize-recover=all) 44 | endif() 45 | 46 | include(FetchContent) 47 | 48 | FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz) 49 | FetchContent_MakeAvailable(json) 50 | 51 | find_package(jwt-cpp QUIET) 52 | 53 | if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 54 | # the unit tests can be built as part of the sdk (in which case it will 55 | # link against the build tree) or it can be built standalone in which 56 | # case it will link against the installed version using cmake. 57 | # if running as standalone, we need to fetch jwt-cpp 58 | 59 | # ideally, in both the cases, we should be able to fetch content jwt-cpp 60 | # but in the sdk build jwt-cpp is handled differently from other dependencies 61 | # because of that, 62 | # we cannot fetch it again here if we build as part of the sdk. 63 | 64 | # therefore, we fetch it only if we build as standalone 65 | 66 | # Set JWT-CPP options before fetching 67 | set(JWT_DISABLE_PICOJSON ON CACHE BOOL "Disable picojson support in jwt-cpp") 68 | set(JWT_BUILD_EXAMPLES OFF CACHE BOOL "Disable building jwt-cpp examples") 69 | 70 | FetchContent_Declare( 71 | jwt-cpp 72 | GIT_REPOSITORY https://github.com/Thalhammer/jwt-cpp.git 73 | GIT_TAG v0.7.1 # Use the latest stable version 74 | EXCLUDE_FROM_ALL 75 | ) 76 | 77 | # the fetch content for jwt-cpp is being handled differently because 78 | # it's headers were getting installed even when using EXCLUDE_FROM_ALL 79 | # presumably, its because jwt-cpp is not respecting all of CMAKE's rules 80 | # this way prevents the headers being installed when the sdk is installed 81 | # the headers must not be installed because we want to just link to this 82 | # statically. there is no need to add unnecessary libraries to target machines. 83 | FetchContent_Populate(jwt-cpp) 84 | add_library(own-jwt-cpp INTERFACE) 85 | target_include_directories(own-jwt-cpp 86 | INTERFACE ${jwt-cpp_SOURCE_DIR}/include) 87 | # jwt-cpp is advertized as a c++11 library. but it somehow uses c++17 features, 88 | # but it should work with c++14 also. so disable this warning. 89 | target_compile_options(own-jwt-cpp INTERFACE -Wno-c++17-extensions) 90 | endif() 91 | 92 | target_link_libraries(nv-attestation-unit-tests PRIVATE 93 | GTest::gtest 94 | GTest::gmock 95 | nlohmann_json::nlohmann_json 96 | # link regarless of whether we are building as part of the sdk or standalone 97 | # if built as part of the sdk, the cmake in sdk will have 98 | # made this available. 99 | own-jwt-cpp 100 | ) 101 | 102 | if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 103 | # CMake file is being run on its own (standalone) - testing installed version of sdk 104 | find_package(nvat REQUIRED) 105 | target_link_libraries(nv-attestation-unit-tests PRIVATE nvat::nvat) 106 | target_include_directories(nv-attestation-unit-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) 107 | else() 108 | # CMake file is being invoked as part of subdirectory from another CMake file 109 | target_link_libraries(nv-attestation-unit-tests PRIVATE nvat) 110 | target_include_directories(nv-attestation-unit-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) 111 | endif() 112 | 113 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/testdata 114 | DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 115 | 116 | include(GoogleTest) 117 | 118 | gtest_discover_tests(nv-attestation-unit-tests PROPERTIES LABELS "unit") -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/include/nv_attestation/spdm/spdm_measurement_records.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | // This SDK headers 28 | #include "nv_attestation/log.h" 29 | #include "nv_attestation/error.h" 30 | #include "nv_attestation/utils.h" 31 | 32 | namespace nvattestation { 33 | 34 | /** 35 | * @brief Represents a DMTF-specified measurement value. 36 | * Structure based on DMTF SPDM specification (e.g., DSP0274). 37 | */ 38 | struct DmtfMeasurementBlock { 39 | uint8_t m_type{}; 40 | uint16_t m_value_size{}; 41 | std::vector m_value; 42 | 43 | static std::unique_ptr create(const std::vector& data, size_t offset); 44 | 45 | uint8_t get_measurement_value_type() const { return m_type; } 46 | uint16_t get_measurement_value_size() const { return m_value_size; } 47 | const std::vector& get_measurement_value() const { return m_value; } 48 | 49 | private: 50 | /** 51 | * @brief Parses the raw DMTF measurement data. 52 | * @param data The byte vector containing the raw DMTF measurement data block. 53 | * @param offset Current offset into the data vector. 54 | * @return True if parsing was successful, false otherwise. 55 | */ 56 | bool parse(const std::vector& data, size_t& offset); 57 | 58 | static const size_t kDmtfSpecMeasurementValueTypeSize = 1; 59 | static const size_t kDmtfSpecMeasurementValueSizeSize = 2; // Little-endian 60 | }; 61 | 62 | // Forward declaration for ostream operator 63 | std::ostream& operator<<(std::ostream& os, const DmtfMeasurementBlock& dmtf_measurement); 64 | 65 | /** 66 | * @brief Parses the SPDM Measurement Record data. 67 | * The Measurement Record consists of one or more Measurement Blocks. 68 | */ 69 | class SpdmMeasurementRecordParser { 70 | public: 71 | static std::unique_ptr create(const std::vector& record_data, uint8_t num_blocks); 72 | 73 | Error get_dmtf_measurement_block(uint8_t index, DmtfMeasurementBlock& out_measurement_block) const { 74 | auto it = m_dmtf_measurement_blocks.find(index); 75 | if (it == m_dmtf_measurement_blocks.end()) { 76 | LOG_ERROR("measurement block with index " + std::to_string(index) + " is not present."); 77 | return Error::SpdmFieldNotFound; 78 | } 79 | out_measurement_block = *(it->second); 80 | return Error::Ok; 81 | } 82 | 83 | const std::unordered_map>& get_all_measurement_blocks() const { return m_dmtf_measurement_blocks; } 84 | 85 | /** 86 | * @brief Constant indicating the DMTF specified measurement type. 87 | * Bit 0 = 1 indicates DMTF-specified measurement. 88 | */ 89 | static constexpr uint8_t kMeasurementSpecificationDmtf = 1; 90 | 91 | private: 92 | static const size_t kIndexSize = 1; 93 | static const size_t kMeasurementSpecificationSize = 1; 94 | static const size_t kMeasurementSizeSize = 2; // Little-endian 95 | 96 | static const uint8_t kMeasurementSpecification = 0x01; 97 | 98 | uint8_t m_num_blocks; 99 | 100 | /** 101 | * @brief Parses the entire measurement record data. 102 | * @param record_data The raw byte vector containing the complete measurement record. 103 | * @param num_blocks The number of measurement blocks expected, as indicated by 104 | * the NumberOfBlocks field in the SPDM GET_MEASUREMENTS response. 105 | * @return True if parsing all blocks was successful, false otherwise. 106 | */ 107 | bool parse(const std::vector& record_data, uint8_t num_blocks); 108 | 109 | bool parse_measurement_block(const std::vector& record_data, size_t& offset); 110 | 111 | // Map from index to measurement block for efficient lookup 112 | std::unordered_map> m_dmtf_measurement_blocks; 113 | 114 | }; 115 | 116 | // Forward declaration for ostream operator 117 | std::ostream& operator<<(std::ostream& os, const SpdmMeasurementRecordParser& parser); 118 | 119 | } // namespace nvattestation -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/test_utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "test_utils.h" 19 | #include "nv_attestation/gpu/claims.h" 20 | #include "nv_attestation/claims.h" 21 | 22 | // Default constructor implementation with Hopper GPU data 23 | MockGpuEvidenceData::MockGpuEvidenceData() 24 | : architecture(GpuArchitecture::Hopper), 25 | board_id(11111), 26 | uuid("GPU-11111111-2222-3333-4444-555555555555"), 27 | vbios_version("96.00.9F.00.01"), 28 | driver_version("550.90.07"), 29 | nonce("931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb"), 30 | attestation_report_path("testdata/hopperAttestationReport.txt"), 31 | attestation_cert_chain_path("testdata/hopperCertChain.txt") { 32 | } 33 | 34 | // Factory method implementations for MockGpuEvidenceData 35 | 36 | MockGpuEvidenceData MockGpuEvidenceData::create_default() { 37 | return MockGpuEvidenceData(); 38 | } 39 | 40 | MockGpuEvidenceData MockGpuEvidenceData::create_bad_nonce_scenario() { 41 | return MockGpuEvidenceData( 42 | GpuArchitecture::Hopper, 43 | 11111, 44 | "GPU-11111111-2222-3333-4444-555555555555", 45 | "96.00.5E.00.01", 46 | "535.86.09", 47 | "0000000000000000000000000000000000000000000000000000000000000000", 48 | "testdata/sample_attestation_data/gpu/hopperAttestationReport.txt", 49 | "testdata/sample_attestation_data/gpu/hopperCertChain.txt" 50 | ); 51 | } 52 | 53 | MockGpuEvidenceData MockGpuEvidenceData::create_invalid_signature_scenario() { 54 | return MockGpuEvidenceData( 55 | GpuArchitecture::Hopper, 56 | 11111, 57 | "GPU-11111111-2222-3333-4444-555555555555", 58 | "96.00.9F.00.01", 59 | "550.90.07", 60 | "931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb", 61 | "testdata/sample_attestation_data/gpu/hopperAttestationReportInvalidSignature.txt", 62 | "testdata/sample_attestation_data/gpu/hopperCertChainExpired.txt" 63 | ); 64 | } 65 | 66 | MockGpuEvidenceData MockGpuEvidenceData::create_expired_driver_rim_scenario() { 67 | return MockGpuEvidenceData( 68 | GpuArchitecture::Hopper, 69 | 11111, 70 | "GPU-11111111-2222-3333-4444-555555555555", 71 | "96.00.5E.00.04", 72 | "570.124.03", 73 | "931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb", 74 | "testdata/sample_attestation_data/gpu/hopperAttestationReportExpired.txt", 75 | "testdata/sample_attestation_data/gpu/hopperCertChainExpired.txt" 76 | ); 77 | } 78 | 79 | MockGpuEvidenceData MockGpuEvidenceData::create_measurements_mismatch_scenario() { 80 | return MockGpuEvidenceData( 81 | GpuArchitecture::Hopper, 82 | 11111, 83 | "GPU-11111111-2222-3333-4444-555555555555", 84 | "96.00.5E.00.01", 85 | "535.86.09", 86 | "27a328247bf7935c993341cf587be6f05986ccce4fe7ba2c54100bd616a58f66", 87 | "testdata/sample_attestation_data/gpu/hopperAttestationReport.txt", 88 | "testdata/sample_attestation_data/gpu/hopperCertChain.txt" 89 | ); 90 | } 91 | 92 | MockGpuEvidenceData MockGpuEvidenceData::create_blackwell_scenario() { 93 | return MockGpuEvidenceData( 94 | GpuArchitecture::Blackwell, 95 | 11111, 96 | "GPU-11111111-2222-3333-4444-555555555555", 97 | "97.00.88.00.0F", 98 | "575.32", 99 | "931d8dd0add203ac3d8b4fbde75e115278eefcdceac5b87671a748f32364dfcb", 100 | "testdata/sample_attestation_data/gpu/blackwellAttestationReport.txt", 101 | "testdata/sample_attestation_data/gpu/blackwellCertChain.txt" 102 | ); 103 | } 104 | 105 | Error get_git_repo_root(std::string& out_git_repo_root) { 106 | std::string git_cmd = "git rev-parse --show-toplevel 2>/dev/null"; 107 | FILE* pipe = popen(git_cmd.c_str(), "r"); 108 | if (pipe) { 109 | char buffer[1024]; 110 | if (fgets(buffer, sizeof(buffer), pipe) != nullptr) { 111 | std::string repo_root = std::string(buffer); 112 | if (!repo_root.empty() && repo_root.back() == '\n') { 113 | repo_root.pop_back(); 114 | } 115 | out_git_repo_root = repo_root; 116 | return Error::Ok; 117 | } 118 | } 119 | return Error::InternalError; 120 | } -------------------------------------------------------------------------------- /nv-attestation-sdk-cpp/unit-tests/testdata/hopperCertChain.txt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDfTCCAwKgAwIBAgIUU8IroV5daAiCgtoHTtn7N6pYV3EwCgYIKoZIzj0EAwMw 3 | ZDEbMBkGA1UEBRMSNDE0MzFENDgwRkU1RTg3Mjc0MQswCQYDVQQGEwJVUzEbMBkG 4 | A1UECgwSTlZJRElBIENvcnBvcmF0aW9uMRswGQYDVQQDDBJHSDEwMCBBMDEgR1NQ 5 | IEJST00wIBcNMjAxMDE3MDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMHwxMTAvBgNV 6 | BAUTKDUzQzIyQkExNUU1RDY4MDg4MjgyREEwNzRFRDlGQjM3QUE1ODU3NzExCzAJ 7 | BgNVBAYTAlVTMRswGQYDVQQKDBJOVklESUEgQ29ycG9yYXRpb24xHTAbBgNVBAMM 8 | FEdIMTAwIEEwMSBHU1AgRk1DIExGMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEgDPx 9 | q23XZIuWevUXqLFHMD7bTiPOocq/1+RPjdVkBDxIlQpP2AjxfBSIYYcCN55G0vjO 10 | UFeFv8cx4NJSoCYyPWK/EvFNdyy3RNv00pdWU3ZAQmGOcorOJ+eUnWR/6Wjto4IB 11 | WTCCAVUwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBTTwiuhXl1oCIKC2gdO2fs3 12 | qlhXcTAfBgNVHSMEGDAWgBTPzHFrUzj0etDtUvSant7I+soqTzA4BgNVHREEMTAv 13 | oC0GCisGAQQBgxyCEgGgHwwdTlZJRElBOkdIMTAwOjQ4QjAyRDkyNDk0QkFERjQw 14 | gcgGBmeBBQUEAQSBvTCBugIBATB2MBAGByqGSM49AgEGBSuBBAAiA2IABE9Q2m4E 15 | enmB6sPZ4qh+gs85UTtdyS+/GuP5v+8IW5KaDhKJSMFQAumGGCpY1gS16l5C/p5H 16 | 7i21IYxsxrUedEtgfcdse7hYDNoE2yexPpSbzTB6WSeKiTjnrbexkGdvlzA9Bglg 17 | hkgBZQMEAgIEMPXDhK67V5IXosZrF+0PKOapuNY5BBrNe0chzsAE9ydUlLqUu1zf 18 | 2zBV7gUXYrH3XTAKBggqhkjOPQQDAwNpADBmAjEA7ooRPcqt9nC1Yo+zRV2NG2cP 19 | kG2mt2xVrp7KvoF7xs1mpXbGSo4Ye4bgcYOWJ/CEAjEArMWN40TlJ1DuDKV1jw10 20 | xoRzSZuvnn41eav2pKu0Pkoa2Cdy5Sk9lv0fIB1vsKAf 21 | -----END CERTIFICATE----- 22 | -----BEGIN CERTIFICATE----- 23 | MIICUDCCAdagAwIBAgIJQUMdSA/l6HJ0MAoGCCqGSM49BAMDMFMxJzAlBgNVBAMM 24 | Hk5WSURJQSBHSDEwMCBQcm92aXNpb25lciBJQ0EgMTEbMBkGA1UECgwSTlZJRElB 25 | IENvcnBvcmF0aW9uMQswCQYDVQQGEwJVUzAgFw0yMDEwMTcwMDAwMDBaGA85OTk5 26 | MTIzMTIzNTk1OVowZDEbMBkGA1UEBRMSNDE0MzFENDgwRkU1RTg3Mjc0MQswCQYD 27 | VQQGEwJVUzEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0aW9uMRswGQYDVQQDDBJH 28 | SDEwMCBBMDEgR1NQIEJST00wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARPUNpuBHp5 29 | gerD2eKofoLPOVE7Xckvvxrj+b/vCFuSmg4SiUjBUALphhgqWNYEtepeQv6eR+4t 30 | tSGMbMa1HnRLYH3HbHu4WAzaBNsnsT6Um80welkniok45623sZBnb5ejYzBhMA8G 31 | A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBTPzHFrUzj0 32 | etDtUvSant7I+soqTzAfBgNVHSMEGDAWgBQpaMsWLNB3lXKieRAD5p66DMwKlDAK 33 | BggqhkjOPQQDAwNoADBlAjEArfqR6WTTScWTej2Ib/Ow0WZDty+pLP8kYmmf8H7a 34 | txQabkBkYrd6sqJfw+YSM9RKAjAbl2SG6I0fQ+mbpFMX4bFf7JF0V2ln5phOBGLi 35 | 0qmpbZ5H3cZkuK1g3xxda6ru4PE= 36 | -----END CERTIFICATE----- 37 | -----BEGIN CERTIFICATE----- 38 | MIICqjCCAi+gAwIBAgIQav5xhPkiMsjfeyQiYXduVjAKBggqhkjOPQQDAzA9MR4w 39 | HAYDVQQDDBVOVklESUEgR0gxMDAgSWRlbnRpdHkxGzAZBgNVBAoMEk5WSURJQSBD 40 | b3Jwb3JhdGlvbjAgFw0yMjAzMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowUzEn 41 | MCUGA1UEAwweTlZJRElBIEdIMTAwIFByb3Zpc2lvbmVyIElDQSAxMRswGQYDVQQK 42 | DBJOVklESUEgQ29ycG9yYXRpb24xCzAJBgNVBAYTAlVTMHYwEAYHKoZIzj0CAQYF 43 | K4EEACIDYgAEzUdWqjn1OlXhLfFOKAFTghqG+Q3zF4xgSBbZsUEyWYCC3rKjE9Nn 44 | o88ZpBQx85Oo0PkqP2dwoMVNTQMv5cvy9jLaTvSTXZwN2HQHE9u7x7BIYrWi0sG3 45 | 5q1IJNSOGO5Lo4HbMIHYMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG 46 | MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwubmRpcy5udmlkaWEuY29tL2Ny 47 | bC9sMi1naDEwMC5jcmwwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRw 48 | Oi8vb2NzcC5uZGlzLm52aWRpYS5jb20wHQYDVR0OBBYEFCloyxYs0HeVcqJ5EAPm 49 | nroMzAqUMB8GA1UdIwQYMBaAFAdCoOsDnIBge6FBYZlNriX3wpseMAoGCCqGSM49 50 | BAMDA2kAMGYCMQDK0BCr49DNJ48Yh5wu388bZifDFxAsiUS4U1fGmpJZFhCbODH6 51 | mRwcMxp6EOayZuYCMQDYKTyNc2FxWFuhHtdCE3ls4S7SInehdErTZNuhFymc4YOM 52 | 6VlLWTY/CM+resjjqxQ= 53 | -----END CERTIFICATE----- 54 | -----BEGIN CERTIFICATE----- 55 | MIICijCCAhCgAwIBAgIQTCVe3jvQAb8/SjtgX8qJijAKBggqhkjOPQQDAzA1MSIw 56 | IAYDVQQDDBlOVklESUEgRGV2aWNlIElkZW50aXR5IENBMQ8wDQYDVQQKDAZOVklE 57 | SUEwIBcNMjIwMTEyMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMD0xHjAcBgNVBAMM 58 | FU5WSURJQSBHSDEwMCBJZGVudGl0eTEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0 59 | aW9uMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE+pg+tDUuILlZILk5wg22YEJ9Oh6c 60 | yPcsv3IvgRWcV4LeZK1pTCoQDIplZ0E4qsLG3G04pxsbMhxbqkiz9pqlTV2rtuVg 61 | SmIqnSYkU1jWXsPS9oVLCGE8VRLl1JvqyOxUo4HaMIHXMA8GA1UdEwEB/wQFMAMB 62 | Af8wDgYDVR0PAQH/BAQDAgEGMDsGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwu 63 | bmRpcy5udmlkaWEuY29tL2NybC9sMS1yb290LmNybDA3BggrBgEFBQcBAQQrMCkw 64 | JwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLm5kaXMubnZpZGlhLmNvbTAdBgNVHQ4E 65 | FgQUB0Kg6wOcgGB7oUFhmU2uJffCmx4wHwYDVR0jBBgwFoAUV4X/g/JjzGV9aLc6 66 | W/SNSsv7SV8wCgYIKoZIzj0EAwMDaAAwZQIxAPIQhnveFxYIrPzBqViT2I34SfS4 67 | JGWFnk/1UcdmgJmp+7l6rH/C4qxwntYSgeYrlQIwdjQuofHnhd1RL09OBO34566J 68 | C9bYAosT/86cCojiGjhLnal9hJOH0nS/lrbaoc5a 69 | -----END CERTIFICATE----- 70 | -----BEGIN CERTIFICATE----- 71 | MIICCzCCAZCgAwIBAgIQLTZwscoQBBHB/sDoKgZbVDAKBggqhkjOPQQDAzA1MSIw 72 | IAYDVQQDDBlOVklESUEgRGV2aWNlIElkZW50aXR5IENBMQ8wDQYDVQQKDAZOVklE 73 | SUEwIBcNMjExMTA1MDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMDUxIjAgBgNVBAMM 74 | GU5WSURJQSBEZXZpY2UgSWRlbnRpdHkgQ0ExDzANBgNVBAoMBk5WSURJQTB2MBAG 75 | ByqGSM49AgEGBSuBBAAiA2IABA5MFKM7+KViZljbQSlgfky/RRnEQScW9NDZF8SX 76 | gAW96r6u/Ve8ZggtcYpPi2BS4VFu6KfEIrhN6FcHG7WP05W+oM+hxj7nyA1r1jkB 77 | 2Ry70YfThX3Ba1zOryOP+MJ9vaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B 78 | Af8EBAMCAQYwHQYDVR0OBBYEFFeF/4PyY8xlfWi3Olv0jUrL+0lfMB8GA1UdIwQY 79 | MBaAFFeF/4PyY8xlfWi3Olv0jUrL+0lfMAoGCCqGSM49BAMDA2kAMGYCMQCPeFM3 80 | TASsKQVaT+8S0sO9u97PVGCpE9d/I42IT7k3UUOLSR/qvJynVOD1vQKVXf0CMQC+ 81 | EY55WYoDBvs2wPAH1Gw4LbcwUN8QCff8bFmV4ZxjCRr4WXTLFHBKjbfneGSBWwA= 82 | -----END CERTIFICATE----- --------------------------------------------------------------------------------