|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Linq;
using Microsoft.AspNetCore.DataProtection.Test.Shared;
using Microsoft.AspNetCore.InternalTesting;
using Xunit;
namespace Microsoft.AspNetCore.Cryptography.Cng;
public unsafe class BCryptUtilTests
{
[ConditionalFact]
[ConditionalRunTestOnlyOnWindows]
public void GenRandom_PopulatesBuffer()
{
// Arrange
byte[] bytes = new byte[sizeof(Guid) + 6];
bytes[0] = 0x04; // leading canary
bytes[1] = 0x10;
bytes[2] = 0xE4;
bytes[sizeof(Guid) + 3] = 0xEA; // trailing canary
bytes[sizeof(Guid) + 4] = 0xF2;
bytes[sizeof(Guid) + 5] = 0x6A;
fixed (byte* pBytes = &bytes[3])
{
for (int i = 0; i < 100; i++)
{
// Act
BCryptUtil.GenRandom(pBytes, (uint)sizeof(Guid));
// Check that the canaries haven't changed
Assert.Equal(0x04, bytes[0]);
Assert.Equal(0x10, bytes[1]);
Assert.Equal(0xE4, bytes[2]);
Assert.Equal(0xEA, bytes[sizeof(Guid) + 3]);
Assert.Equal(0xF2, bytes[sizeof(Guid) + 4]);
Assert.Equal(0x6A, bytes[sizeof(Guid) + 5]);
// Check that the buffer was actually filled.
// This check will fail once every 2**128 runs, which is insignificant.
Guid newGuid = new Guid(bytes.Skip(3).Take(sizeof(Guid)).ToArray());
Assert.NotEqual(Guid.Empty, newGuid);
// Check that the first and last bytes of the buffer are not zero, which indicates that they
// were in fact filled. This check will fail around 0.8% of the time, so we'll iterate up
// to 100 times, which puts the total failure rate at once every 2**700 runs,
// which is insignificant.
if (bytes[3] != 0x00 && bytes[18] != 0x00)
{
return; // success!
}
}
}
Assert.Fail("Buffer was not filled as expected.");
}
}
|