CngAuthenticatedEncryptorBaseTests.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright (c) .NET Foundation. All rights reserved.
  2. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  3. using System;
  4. using Microsoft.AspNetCore.DataProtection.Test.Shared;
  5. using Microsoft.AspNetCore.Testing.xunit;
  6. using Moq;
  7. using Xunit;
  8. namespace Microsoft.AspNetCore.DataProtection.Cng.Internal
  9. {
  10. public unsafe class CngAuthenticatedEncryptorBaseTests
  11. {
  12. [Fact]
  13. public void Decrypt_ForwardsArraySegment()
  14. {
  15. // Arrange
  16. var ciphertext = new ArraySegment<byte>(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 }, 3, 2);
  17. var aad = new ArraySegment<byte>(new byte[] { 0x10, 0x11, 0x12, 0x13, 0x14 }, 1, 4);
  18. var encryptorMock = new Mock<MockableEncryptor>();
  19. encryptorMock
  20. .Setup(o => o.DecryptHook(It.IsAny<IntPtr>(), 2, It.IsAny<IntPtr>(), 4))
  21. .Returns((IntPtr pbCiphertext, uint cbCiphertext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData) =>
  22. {
  23. // ensure that pointers started at the right place
  24. Assert.Equal((byte)0x03, *(byte*)pbCiphertext);
  25. Assert.Equal((byte)0x11, *(byte*)pbAdditionalAuthenticatedData);
  26. return new byte[] { 0x20, 0x21, 0x22 };
  27. });
  28. // Act
  29. var retVal = encryptorMock.Object.Decrypt(ciphertext, aad);
  30. // Assert
  31. Assert.Equal(new byte[] { 0x20, 0x21, 0x22 }, retVal);
  32. }
  33. [Fact]
  34. public void Decrypt_HandlesEmptyAADPointerFixup()
  35. {
  36. // Arrange
  37. var ciphertext = new ArraySegment<byte>(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 }, 3, 2);
  38. var aad = new ArraySegment<byte>(new byte[0]);
  39. var encryptorMock = new Mock<MockableEncryptor>();
  40. encryptorMock
  41. .Setup(o => o.DecryptHook(It.IsAny<IntPtr>(), 2, It.IsAny<IntPtr>(), 0))
  42. .Returns((IntPtr pbCiphertext, uint cbCiphertext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData) =>
  43. {
  44. // ensure that pointers started at the right place
  45. Assert.Equal((byte)0x03, *(byte*)pbCiphertext);
  46. Assert.NotEqual(IntPtr.Zero, pbAdditionalAuthenticatedData); // CNG will complain if this pointer is zero
  47. return new byte[] { 0x20, 0x21, 0x22 };
  48. });
  49. // Act
  50. var retVal = encryptorMock.Object.Decrypt(ciphertext, aad);
  51. // Assert
  52. Assert.Equal(new byte[] { 0x20, 0x21, 0x22 }, retVal);
  53. }
  54. [Fact]
  55. public void Decrypt_HandlesEmptyCiphertextPointerFixup()
  56. {
  57. // Arrange
  58. var ciphertext = new ArraySegment<byte>(new byte[0]);
  59. var aad = new ArraySegment<byte>(new byte[] { 0x10, 0x11, 0x12, 0x13, 0x14 }, 1, 4);
  60. var encryptorMock = new Mock<MockableEncryptor>();
  61. encryptorMock
  62. .Setup(o => o.DecryptHook(It.IsAny<IntPtr>(), 0, It.IsAny<IntPtr>(), 4))
  63. .Returns((IntPtr pbCiphertext, uint cbCiphertext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData) =>
  64. {
  65. // ensure that pointers started at the right place
  66. Assert.NotEqual(IntPtr.Zero, pbCiphertext); // CNG will complain if this pointer is zero
  67. Assert.Equal((byte)0x11, *(byte*)pbAdditionalAuthenticatedData);
  68. return new byte[] { 0x20, 0x21, 0x22 };
  69. });
  70. // Act
  71. var retVal = encryptorMock.Object.Decrypt(ciphertext, aad);
  72. // Assert
  73. Assert.Equal(new byte[] { 0x20, 0x21, 0x22 }, retVal);
  74. }
  75. public abstract class MockableEncryptor : CngAuthenticatedEncryptorBase
  76. {
  77. public override void Dispose()
  78. {
  79. }
  80. public abstract byte[] DecryptHook(IntPtr pbCiphertext, uint cbCiphertext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData);
  81. protected override sealed unsafe byte[] DecryptImpl(byte* pbCiphertext, uint cbCiphertext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData)
  82. {
  83. return DecryptHook((IntPtr)pbCiphertext, cbCiphertext, (IntPtr)pbAdditionalAuthenticatedData, cbAdditionalAuthenticatedData);
  84. }
  85. public abstract byte[] EncryptHook(IntPtr pbPlaintext, uint cbPlaintext, IntPtr pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer);
  86. protected override sealed unsafe byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer)
  87. {
  88. return EncryptHook((IntPtr)pbPlaintext, cbPlaintext, (IntPtr)pbAdditionalAuthenticatedData, cbAdditionalAuthenticatedData, cbPreBuffer, cbPostBuffer);
  89. }
  90. }
  91. }
  92. }