Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/7.0-staging] Skip RC2 encrypted PKCS12 files on Android for iteration counting #88854

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using Test.Cryptography;
using Xunit;

namespace System.Security.Cryptography.X509Certificates.Tests
Expand All @@ -18,7 +19,7 @@ public class PfxIterationCountTests_CustomAppDomainDataLimit

[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))]
public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNotExceedingDefaultLimit(string name, bool usesPbes2, byte[] blob, long iterationCount)
public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNotExceedingDefaultLimit(string name, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2)
{
_ = iterationCount;
_ = blob;
Expand All @@ -28,6 +29,11 @@ public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNo
throw new SkipTestException(name + " uses PBES2 which is not supported on this version.");
}

if (usesRC2 && !PlatformSupport.IsRC2Supported)
{
throw new SkipTestException(name + " uses RC2, which is not supported on this platform.");
}

RemoteExecutor.Invoke((certName) =>
{
AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -2);
Expand All @@ -41,7 +47,7 @@ public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNo

[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountExceedingDefaultLimit_MemberData), MemberType = typeof(PfxIterationCountTests))]
public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount)
public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2)
{
_ = password;
_ = iterationCount;
Expand All @@ -52,6 +58,11 @@ public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLi
throw new SkipTestException(name + " uses PBES2 which is not supported on this version.");
}

if (usesRC2 && !PlatformSupport.IsRC2Supported)
{
throw new SkipTestException(name + " uses RC2, which is not supported on this platform.");
}

RemoteExecutor.Invoke((certName) =>
{
AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -2);
Expand All @@ -65,7 +76,7 @@ public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLi

[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))]
public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultLimit_Throws(string name, bool usesPbes2, byte[] blob, long iterationCount)
public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultLimit_Throws(string name, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2)
{
_ = iterationCount;
_ = blob;
Expand All @@ -75,6 +86,11 @@ public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultL
throw new SkipTestException(name + " uses PBES2 which is not supported on this version.");
}

if (usesRC2 && !PlatformSupport.IsRC2Supported)
{
throw new SkipTestException(name + " uses RC2, which is not supported on this platform.");
}

RemoteExecutor.Invoke((certName) =>
{
AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", 0);
Expand All @@ -88,7 +104,7 @@ public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultL

[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountExceedingDefaultLimit_MemberData), MemberType = typeof(PfxIterationCountTests))]
public void Import_AppDomainDataWithValueMinusOne_IterationCountExceedingDefaultLimit(string name, string password, bool usesPbes2, byte[] blob, long iterationCount)
public void Import_AppDomainDataWithValueMinusOne_IterationCountExceedingDefaultLimit(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2)
{
_ = password;
_ = blob;
Expand All @@ -99,6 +115,11 @@ public void Import_AppDomainDataWithValueMinusOne_IterationCountExceedingDefault
throw new SkipTestException(name + " uses PBES2 which is not supported on this version.");
}

if (usesRC2 && !PlatformSupport.IsRC2Supported)
{
throw new SkipTestException(name + " uses RC2, which is not supported on this platform.");
}

RemoteExecutor.Invoke((certName) =>
{
AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ public abstract partial class PfxIterationCountTests

[ConditionalTheory]
[MemberData(nameof(GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData))]
public void Import_IterationCounLimitNotExceeded_Succeeds(string name, bool usesPbes2, byte[] blob, long iterationCount)
public void Import_IterationCounLimitNotExceeded_Succeeds(string name, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2)
{
if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported)
{
throw new SkipTestException(name + " uses PBES2 which is not supported on this version.");
}

if (usesRC2 && !PlatformSupport.IsRC2Supported)
{
throw new SkipTestException(name + " uses RC2, which is not supported on this platform.");
}

if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations))
{
X509Certificate cert = Import(blob);
Expand All @@ -38,7 +43,7 @@ public void Import_IterationCounLimitNotExceeded_Succeeds(string name, bool uses

[ConditionalTheory]
[MemberData(nameof(GetCertsWith_IterationCountExceedingDefaultLimit_MemberData))]
public void Import_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount)
public void Import_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2)
{
_ = password;
_ = iterationCount;
Expand All @@ -48,19 +53,29 @@ public void Import_IterationCountLimitExceeded_Throws(string name, string passwo
throw new SkipTestException(name + " uses PBES2 which is not supported on this version.");
}

if (usesRC2 && !PlatformSupport.IsRC2Supported)
{
throw new SkipTestException(name + " uses RC2, which is not supported on this platform.");
}

CryptographicException ce = Assert.Throws<CryptographicException>(() => Import(blob));
Assert.Contains("2233907", ce.Message);
}

[ConditionalTheory]
[MemberData(nameof(GetCertsWith_IterationCountExceedingDefaultLimit_MemberData))]
public void ImportWithPasswordOrFileName_IterationCountLimitExceeded(string name, string password, bool usesPbes2, byte[] blob, long iterationCount)
public void ImportWithPasswordOrFileName_IterationCountLimitExceeded(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2)
{
if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported)
{
throw new SkipTestException(name + " uses PBES2 which is not supported on this version.");
}

if (usesRC2 && !PlatformSupport.IsRC2Supported)
{
throw new SkipTestException(name + " uses RC2, which is not supported on this platform.");
}

using (TempFileHolder tempFile = new TempFileHolder(blob))
{
string fileName = tempFile.FilePath;
Expand Down Expand Up @@ -99,13 +114,18 @@ internal static void VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(Actio

[ConditionalTheory]
[MemberData(nameof(GetCertsWith_NonNullOrEmptyPassword_MemberData))]
public void Import_NonNullOrEmptyPasswordExpected_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount)
public void Import_NonNullOrEmptyPasswordExpected_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2)
{
if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported)
{
throw new SkipTestException(name + " uses PBES2 which is not supported on this version.");
}

if (usesRC2 && !PlatformSupport.IsRC2Supported)
{
throw new SkipTestException(name + " uses RC2, which is not supported on this platform.");
}

CryptographicException ce = Assert.ThrowsAny<CryptographicException>(() => Import(blob));

if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations))
Expand Down Expand Up @@ -139,7 +159,7 @@ internal static List<PfxInfo> GetCertificates()
certificates.Add(new PfxInfo(
nameof(TestData.Pkcs12WindowsDotnetExportEmptyPassword), "", 6000, false, TestData.Pkcs12WindowsDotnetExportEmptyPassword.HexToByteArray()));
certificates.Add(new PfxInfo(
nameof(TestData.Pkcs12MacosKeychainCreated), null, 4097, false, TestData.Pkcs12MacosKeychainCreated.HexToByteArray()));
nameof(TestData.Pkcs12MacosKeychainCreated), null, 4097, false, TestData.Pkcs12MacosKeychainCreated.HexToByteArray(), usesRC2: true));
certificates.Add(new PfxInfo(
nameof(TestData.Pkcs12BuilderSaltWithMacNullPassword), null, 120000, true, TestData.Pkcs12BuilderSaltWithMacNullPassword.HexToByteArray()));
certificates.Add(new PfxInfo(
Expand All @@ -162,23 +182,23 @@ public static IEnumerable<object[]> GetCertsWith_IterationCountNotExceedingDefau
c => c.IterationCount <= DefaultIterationLimit &&
string.IsNullOrEmpty(c.Password)))
{
yield return new object[] { p.Name, p.UsesPbes2, p.Blob, p.IterationCount };
yield return new object[] { p.Name, p.UsesPbes2, p.Blob, p.IterationCount, p.UsesRC2 };
}
}

public static IEnumerable<object[]> GetCertsWith_IterationCountExceedingDefaultLimit_MemberData()
{
foreach (PfxInfo p in s_Certificates.Where(c => c.IterationCount > DefaultIterationLimit))
{
yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount };
yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount, p.UsesRC2 };
}
}

public static IEnumerable<object[]> GetCertsWith_NonNullOrEmptyPassword_MemberData()
{
foreach(PfxInfo p in s_Certificates.Where(c => !string.IsNullOrEmpty(c.Password)))
{
yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount };
yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount, p.UsesRC2 };
}
}
}
Expand All @@ -190,14 +210,16 @@ public class PfxInfo
internal long IterationCount { get; set; }
internal bool UsesPbes2 { get; set; }
internal byte[] Blob { get; set; }
internal bool UsesRC2 { get; set; }

internal PfxInfo(string name, string? password, long iterationCount, bool usesPbes2, byte[] blob)
internal PfxInfo(string name, string password, long iterationCount, bool usesPbes2, byte[] blob, bool usesRC2 = false)
{
Name = name;
Password = password;
IterationCount = iterationCount;
UsesPbes2 = usesPbes2;
Blob = blob;
UsesRC2 = usesRC2;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ public static void CollectionPerphemeralImport_HasKeyName()

[ConditionalTheory]
[MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))]
public static void TestIterationCounter(string name, bool usesPbes2, byte[] blob, int iterationCount)
public static void TestIterationCounter(string name, bool usesPbes2, byte[] blob, int iterationCount, bool usesRC2)
{
_ = iterationCount;

Expand All @@ -477,6 +477,11 @@ public static void TestIterationCounter(string name, bool usesPbes2, byte[] blob
throw new SkipTestException(name + " uses PBES2 which is not supported on this version.");
}

if (usesRC2 && !PlatformSupport.IsRC2Supported)
{
throw new SkipTestException(name + " uses RC2, which is not supported on this platform.");
}

try
{
long count = (long)target(blob);
Expand Down
Loading