Skip to content

Commit

Permalink
Updated TPM attestation APIs to remove BinaryData parameters. (#20843)
Browse files Browse the repository at this point in the history
* Updated TPM attestation APIs at the request of the TPM attestation team
  • Loading branch information
LarryOsterman committed May 5, 2021
1 parent 4e1a7f0 commit 49f34a5
Show file tree
Hide file tree
Showing 12 changed files with 360 additions and 33 deletions.
1 change: 1 addition & 0 deletions sdk/attestation/Azure.Security.Attestation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ to reduce the number of parameters passed into the API.
- The return value of `GetPolicyManagementCertificates` has been changed from `AttestationResult<PolicyCertificatesResult>` to `AttestationResult<IReadOnlyList<X509Certificate2>>` to simplify the experience of retrieving the certificate list. As a consequence of this change, the `PolicyCertificatesResult` type has been removed.
- The unused `TpmAttestationRequest` and `TpmAttestationResponse` types have been removed.
- The `AttestationTokenSigningKey` will now ensure that the public key in the provided certificate is the public key corresponding to the private key.
- `AttestTpm` and `AttestTpmAsync` are changed to accept a new `TpmAttestationRequest` and return a `TpmAttestationResponse` instead of accepting and returning a `BinaryData`. The semantics of the API do not change, just the encapsulation of the BinaryData.

## 1.0.0-beta.2 (2021-04-06)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public AttestationClient(System.Uri endpoint, Azure.Core.TokenCredential credent
public virtual System.Threading.Tasks.Task<Azure.Security.Attestation.AttestationResponse<Azure.Security.Attestation.AttestationResult>> AttestOpenEnclaveAsync(Azure.Security.Attestation.AttestationRequest request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Security.Attestation.AttestationResponse<Azure.Security.Attestation.AttestationResult> AttestSgxEnclave(Azure.Security.Attestation.AttestationRequest request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Security.Attestation.AttestationResponse<Azure.Security.Attestation.AttestationResult>> AttestSgxEnclaveAsync(Azure.Security.Attestation.AttestationRequest request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response<System.BinaryData> AttestTpm(System.BinaryData request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response<System.BinaryData>> AttestTpmAsync(System.BinaryData request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response<Azure.Security.Attestation.TpmAttestationResponse> AttestTpm(Azure.Security.Attestation.TpmAttestationRequest request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.Security.Attestation.TpmAttestationResponse>> AttestTpmAsync(Azure.Security.Attestation.TpmAttestationRequest request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response<System.Collections.Generic.IReadOnlyList<Azure.Security.Attestation.AttestationSigner>> GetSigningCertificates(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response<System.Collections.Generic.IReadOnlyList<Azure.Security.Attestation.AttestationSigner>>> GetSigningCertificatesAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
Expand Down Expand Up @@ -277,4 +277,14 @@ public partial class StoredAttestationPolicy
public StoredAttestationPolicy() { }
public string AttestationPolicy { get { throw null; } set { } }
}
public partial class TpmAttestationRequest
{
public TpmAttestationRequest() { }
public System.BinaryData Data { get { throw null; } set { } }
}
public partial class TpmAttestationResponse
{
internal TpmAttestationResponse() { }
public System.BinaryData Data { get { throw null; } }
}
}
28 changes: 10 additions & 18 deletions sdk/attestation/Azure.Security.Attestation/src/AttestationClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,23 +273,19 @@ private async Task<AttestationResponse<AttestationResult>> AttestOpenEnclaveInte

/// <summary>
/// Attest a TPM based enclave.
/// See https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol for more information.
/// See <seealso href="https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol"/> for more information.
/// </summary>
/// <param name="request"></param>
/// <param name="request">TPM Attestation request.</param>
/// <param name="cancellationToken">Cancellation token used to cancel this operation.</param>
/// <returns>A <see cref="TpmAttestationResponse"/>.</returns>
public virtual Response<BinaryData> AttestTpm(BinaryData request, CancellationToken cancellationToken = default)
/// <returns>A <see cref="TpmAttestationResponse"/> containing the TPM attestation response.</returns>
public virtual Response<TpmAttestationResponse> AttestTpm(TpmAttestationRequest request, CancellationToken cancellationToken = default)
{
Argument.AssertNotNull(request, nameof(request));
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationClient)}.{nameof(AttestTpm)}");
scope.Start();
try
{
var response = _restClient.AttestTpm(new TpmAttestationRequest { Data = request.ToArray() }, cancellationToken);

BinaryData responseData = new BinaryData(response.Value);

return Response.FromValue(responseData, response.GetRawResponse());
return _restClient.AttestTpm(request, cancellationToken);
}
catch (Exception ex)
{
Expand All @@ -300,23 +296,19 @@ public virtual Response<BinaryData> AttestTpm(BinaryData request, CancellationTo

/// <summary>
/// Attest a TPM based enclave.
/// See https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol for more information.
/// See <seealso href="https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol"/> for more information.
/// </summary>
/// <param name="request">Incoming request to send to the TPM attestation service.</param>
/// <param name="request">TPM Attestation request.</param>
/// <param name="cancellationToken">Cancellation token used to cancel this operation.</param>
/// <returns>A <see cref="BinaryData"/> structure containing the value of <see cref="TpmAttestationResponse.Data"/>.</returns>
public virtual async Task<Response<BinaryData>> AttestTpmAsync(BinaryData request, CancellationToken cancellationToken = default)
/// <returns>A <see cref="TpmAttestationResponse"/> containing the TPM attestation response.</returns>
public virtual async Task<Response<TpmAttestationResponse>> AttestTpmAsync(TpmAttestationRequest request, CancellationToken cancellationToken = default)
{
Argument.AssertNotNull(request, nameof(request));
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationClient)}.{nameof(AttestTpm)}");
scope.Start();
try
{
var response = await _restClient.AttestTpmAsync(new TpmAttestationRequest { Data = request.ToArray() }, cancellationToken).ConfigureAwait(false);

BinaryData responseData = new BinaryData(response.Value.Data);

return Response.FromValue(responseData, response.GetRawResponse());
return await _restClient.AttestTpmAsync(request, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
namespace Azure.Security.Attestation
{
/// <summary>
/// Represents a response for a TPM attestation call. See https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol for more information.
/// Represents a request for a TPM attestation call. See <seealso href="https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol"/> for more information.
/// </summary>
[CodeGenModel("TpmAttestationRequest")]
internal partial class TpmAttestationRequest
public partial class TpmAttestationRequest
{
/// <summary>
/// Attestation Response data. See https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol for more details
/// Attestation Request data. See <seealso href="https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol"/> for more details
/// </summary>
public ReadOnlyMemory<byte> Data { get => Base64Url.Decode(InternalData); set => InternalData = Base64Url.Encode(value.ToArray()); }
public BinaryData Data { get => BinaryData.FromBytes(Base64Url.Decode(InternalData)); set => InternalData = Base64Url.Encode(value.ToArray()); }

[CodeGenMember("Data")]
internal string InternalData { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
namespace Azure.Security.Attestation
{
/// <summary>
/// Represents a response for a TPM attestation call. See https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol for more information.
/// Represents a response for a TPM attestation call. See <seealso href="https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol"/> for more information.
/// </summary>
[CodeGenModel("TpmAttestationResponse")]
internal partial class TpmAttestationResponse
public partial class TpmAttestationResponse
{
/// <summary>
/// Attestation Response data. See https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol for more details
/// Attestation Response data. See <seealso href="https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol"/> for more details.
/// </summary>
public ReadOnlyMemory<byte> Data { get => Base64Url.Decode(InternalData); }
public BinaryData Data { get => BinaryData.FromBytes(Base64Url.Decode(InternalData)); }

[CodeGenMember("Data")]
internal string InternalData { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using Azure.Core;
using Azure.Core.TestFramework;
using NUnit.Framework;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Azure.Security.Attestation.Tests
{
Expand Down Expand Up @@ -241,7 +243,7 @@ public async Task AttestOpenEnclaveShared()
});

// Confirm that the attestation token contains the enclave held data we specified.
CollectionAssert.AreEqual(binaryRuntimeData, attestationResult.Value.EnclaveHeldData.ToArray());
CollectionAssert.AreEqual(binaryRuntimeData, attestationResult.Value.EnclaveHeldData.ToArray());
// VERIFY ATTESTATIONRESULT.
// Encrypt Data using DeprecatedEnclaveHeldData
// Send to enclave.
Expand Down Expand Up @@ -338,5 +340,47 @@ public async Task AttestOpenEnclaveSharedCallbackRejects()
Assert.IsTrue(callbackInvoked);
}
}

private class TpmInit
{
[JsonPropertyName("type")]
public string Type { get; set; }
}

// TpmAttest requires a TpmPayload object.
private class TpmPayload
{
[JsonPropertyName("payload")]
public object Payload { get; set; }
}

[RecordedTest]
public async Task AttestTpmMinimalAad()
{
// TPM attestation requires that there be an attestation policy applied before it can succeed.
string attestationPolicy = "version=1.0; authorizationrules{=> permit();}; issuancerules{};";
var adminClient = TestEnvironment.GetAadAdministrationClient(this);

var setResult = await adminClient.SetPolicyAsync(AttestationType.Tpm, attestationPolicy);

var tpmPayload = new TpmPayload
{
Payload = new TpmInit
{
Type = "aikcert"
},
};

var client = TestEnvironment.GetAadAttestationClient(this);
Response<TpmAttestationResponse> tpmResponse = null;
tpmResponse = await client.AttestTpmAsync(new TpmAttestationRequest { Data = BinaryData.FromObjectAsJson(tpmPayload) });

// Make sure that the response from the service looks like it's supposed to look.
var parsedValue = JsonDocument.Parse(tpmResponse.Value.Data);
Assert.IsNotNull(parsedValue.RootElement.GetProperty("payload"));
var payload = parsedValue.RootElement.GetProperty("payload");
Assert.IsNotNull(payload.GetProperty("challenge"));
Assert.IsNotNull(payload.GetProperty("service_context"));
}
}
}
Loading

0 comments on commit 49f34a5

Please sign in to comment.