Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ endif()
if(NOT NUGET_EXE)
message(FATAL_ERROR "CMake could not find the nuget command line tool. Please install it from https://www.nuget.org/downloads and move it to ${CMAKE_CURRENT_SOURCE_DIR}!")
else()
execute_process(COMMAND ${NUGET_EXE} install "Microsoft.Attestation.Client" -Version 1.1.133870390-preview -ExcludeVersion -OutputDirectory ${CMAKE_BINARY_DIR}/packages)
execute_process(COMMAND ${NUGET_EXE} install "Microsoft.Attestation.Client" -Version 1.1.134193605-preview -ExcludeVersion -OutputDirectory ${CMAKE_BINARY_DIR}/packages)
if(NUGET_RESULT)
message(FATAL_ERROR "NuGet package installation failed: ${NUGET_ERROR}")
else()
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ This sample provides the code implementation to perform boot attestation and ret
This sample provides the code implementation to perform boot and TPM key attestation and retrieve an attestation token from Microsoft Azure Attestation.
This sample creates a TPM key named "att_sample_key" which is attested by Microsoft Azure Attestation. The creation of a TPM key may take up to a few minutes depending on the TPM hardware.

### **VBS-Protected key attestation (sample_vbs_protected_key_att.exe)**

This sample provides the code implementation to perform VBS-Protected key attestation and retrieve an attestation token from Microsoft Azure Attestation.
This sample creates a VBS-Protected key named "att_sample_vbs_key" which is attested by Microsoft Azure Attestation. The sample must be run with Virtualization-Based Security enabled on the device.

WARNING: Information regarding VBS-Protected Keys relates to prerelease product that may be substantially modified before it's commercially released.
Microsoft makes no warranties, express or implied, with respect to the information provided here.

### **VBS enclave attestation (sample_enclave_att.exe)**

This sample provides the code implementation to perform VBS enclave attestation and retrieve an attestation token from Microsoft Azure Attestation. A sample enclave is provided in the "enclave" directory.
Expand Down
3 changes: 2 additions & 1 deletion attestation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ endmacro()

define_sample(sample_boot_att FALSE)
define_sample(sample_tpm_key_att FALSE)
define_sample(sample_enclave_att TRUE)
define_sample(sample_enclave_att TRUE)
define_sample(sample_vbs_protected_key_att FALSE)
2 changes: 1 addition & 1 deletion attestation/sample_tpm_key_att.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ int main()
0 // other_keys_count
};

attest(ATT_SESSION_TYPE_TPM, &params, "report_key.jwt");
attest(ATT_SESSION_TYPE_TPM, &params, "report_tpm_key.jwt");
}
catch (const std::exception& ex)
{
Expand Down
97 changes: 97 additions & 0 deletions attestation/sample_vbs_protected_key_att.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//

/**
* WARNING: Information regarding VBS-Protected Keys relates to prerelease product that may be substantially modified before it's commercially released.
* Microsoft makes no warranties, express or implied, with respect to the information provided here.
*/

/**
* @brief This sample provides the code implementation to perform VBS-Protected key attestation,
* and retrieve an attestation token from Microsoft Azure Attestation.
*
* @remark The following environment variables must be set before running the sample.
*
* - AZURE_TENANT_ID: Tenant ID for the Azure account. Used for authenticated calls to the attestation service.
* - AZURE_CLIENT_ID: The client ID to authenticate the request. Used for authenticated calls to the attestation service.
* - AZURE_CLIENT_SECRET: The client secret. Used for authenticated calls to the attestation service.
* - AZURE_MAA_URI: Microsoft Azure Attestation provider's Attest URI (as shown in portal). Format is similar to "https://<ProviderName>.<Region>.attest.azure.net".
*
* In addition, a TPM attestation identity key named 'att_sample_aik' must be created. See README.md for instructions.
*
* Finally, a fixed relying party id and nonce are used in this sample. An application should obtain a per-session nonce from the relying party before making
* the call to the attestation service. TODOs in the code below mark the locations to be updated.
*
*/

#include "utils.h"
#include "attest.h"
#include <string>
#include <vector>
#include <iostream>

#include <att_manager.h>
#include <att_manager_logger.h>

using namespace std;

#define AIK_NAME L"att_sample_aik"

int main()
{
// Adjust log level to your desired level of output.
att_set_log_level(att_log_level_none);
att_set_log_listener(sample_log_listener);

// TODO: Use relying party's id in the line below.
string rp_id{ "https://contoso.com" };
// TODO: Use relying party's per-session nonce below.
vector<uint8_t> rp_nonce{ 'R', 'E','P','L','A','C','E',' ','W','I','T','H', ' ','R','P', ' ','N','O','N','C','E' };

try
{
auto tpm_aik = load_tpm_key(AIK_NAME, true);
auto vbs_protected_key = create_vbs_protected_key(L"att_sample_vbs_key", false);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used "att_sample_vbs_key" to distinguish from the key in the tpm key attestation sample, but I wanted to not make the name such a mouthful ("att_sample_vbs_protected_key"). If I should change the name for correctness, let me know.


att_tpm_aik aik = ATT_TPM_AIK_NCRYPT(tpm_aik.get());
att_tpm_key key = ATT_TPM_KEY_VBS_NCRYPT(vbs_protected_key.get());

att_session_params_tpm params
{
rp_nonce.data(), // relying_party_nonce
rp_nonce.size(), // relying_party_nonce_size
rp_id.c_str(), // relying_party_unique_id
&aik, // aik
&key, // request_key
nullptr, // other_keys
0 // other_keys_count
};

attest(ATT_SESSION_TYPE_TPM, &params, "report_vbs_protected_key.jwt");
}
catch (const std::exception& ex)
{
cout << ex.what() << endl;
}

return 0;

//
// Notice that the report will contain the claim "x-ms-tpm-request-key", which includes the public part of the VBS-protected key in the "jwk" field.
// In addition, the "info" section will contain "vbs_ncrypt", indicating that a VBS-protected key was certified. The fields inside "vbs_ncrypt" attest to the VBS-protected key properties.
// These properties are described in the NCrypt library documentation (https://learn.microsoft.com/en-us/windows/win32/api/ncrypt/nf-ncrypt-ncryptverifyclaim#protectingattesting-private-keys-using-virtualization-based-security-vbs).
// A relying party (RP) should validate several important fields inside "vbs_ncrypt.vbs_trustlet_report" to ensure the key was generated and protected inside a trusted VBS-protected environment:
//
// trustlet_identity - Identifies the VBS trustlet that created or protects the key. The RP should compare this value against an expected trustlet identity to ensure the key originates from a trusted environment.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I should remove descriptions, like for enclave descriptions, let me know. Added descriptions since documentation is limited right now, but I'm assuming that these values will all be properly documented once VBS-protected keys GA

//
// trustlet_svn - The security version number (SVN) of the trustlet. The RP should verify this meets its minimum required SVN.
//
// flags.trustlet_debugged - Indicates whether the trustlet was debugged during key creation or protection. RPs should reject keys where this value is true, as debugged trustlets cannot be trusted.
//
// trustlet_policy - A set of policy entries describing protections applied to the trustlet. For example, policy entry ID=2 determines whether the trustlet is debuggable. RPs should verify policy values to verify that the trustlet meets its security requirements.
//
// These validations allow a relying party to establish that the key is genuinely VBS-backed, it comes from the correct trustlet that has sufficient security level, the environment was not debugged or weakened, and policy constraints match the RP's requirements.
//

}
12 changes: 12 additions & 0 deletions attestation/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ wil::unique_ncrypt_key create_ephemeral_software_key()
return ephemeral_software_key;
}

wil::unique_ncrypt_key create_vbs_protected_key(const wstring& name, bool machine_key)
{
cout << "Creating VBS-Protected key...";

// Pass in nullptr instead of "name.cstr()" if you require an ephemeral key.
wil::unique_ncrypt_key vbs_protected_key = create_key(MS_KEY_STORAGE_PROVIDER, name.c_str(), NCRYPT_OVERWRITE_KEY_FLAG | NCRYPT_REQUIRE_VBS_FLAG | (machine_key ? NCRYPT_MACHINE_KEY_FLAG : 0));

cout << " Done." << endl;

return vbs_protected_key;
}

void sample_log_listener(att_log_source, att_log_level, const char* message)
{
cout << "[LOG] " << message << endl;
Expand Down
3 changes: 3 additions & 0 deletions attestation/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ wil::unique_ncrypt_key create_tpm_key(const std::wstring& name, bool machine_key
// Creates a 2048-bit ephemeral software key using the Software Key Storage Provider.
wil::unique_ncrypt_key create_ephemeral_software_key();

// Creates a 2048-bit VBS-Protected key using the Software Key Storage Provider.
wil::unique_ncrypt_key create_vbs_protected_key(const std::wstring& name, bool machine_key);

// Creates a sample log listener to enable logging from the MAA SDK.
void sample_log_listener(att_log_source, att_log_level, const char* message);

Expand Down