summary refs log tree commit diff
path: root/crypto/test
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2018-10-18 18:15:32 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2018-10-18 18:15:32 +0700
commita3ffd09890cd48bbd21040a49a2399a24f204918 (patch)
tree73baa1e3b656b83b90bfb90cc34ed96c055a62f4 /crypto/test
parentMove generic "...withRSA" handler after PSSwithRSA (diff)
downloadBouncyCastle.NET-ed25519-a3ffd09890cd48bbd21040a49a2399a24f204918.tar.xz
Env. prop.: Org.BouncyCastle.Asn1.AllowUnsafeInteger
- set to "true" to weaken ASN.1 INTEGER checks
- see https://github.com/bcgit/bc-csharp/issues/156
Diffstat (limited to 'crypto/test')
-rw-r--r--crypto/test/UnitTests.csproj1
-rw-r--r--crypto/test/src/asn1/test/ASN1IntegerTest.cs355
-rw-r--r--crypto/test/src/asn1/test/RegressionTest.cs1
3 files changed, 357 insertions, 0 deletions
diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj
index d89cd6d56..2dd3547fa 100644
--- a/crypto/test/UnitTests.csproj
+++ b/crypto/test/UnitTests.csproj
@@ -51,6 +51,7 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="src\asn1\test\ASN1IntegerTest.cs" />
     <Compile Include="src\asn1\test\ASN1SequenceParserTest.cs" />
     <Compile Include="src\asn1\test\ASN1UnitTest.cs" />
     <Compile Include="src\asn1\test\AdditionalInformationSyntaxUnitTest.cs" />
diff --git a/crypto/test/src/asn1/test/ASN1IntegerTest.cs b/crypto/test/src/asn1/test/ASN1IntegerTest.cs
new file mode 100644
index 000000000..6de3f7507
--- /dev/null
+++ b/crypto/test/src/asn1/test/ASN1IntegerTest.cs
@@ -0,0 +1,355 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class Asn1IntegerTest
+        : SimpleTest
+    {
+        private static readonly byte[] suspectKey = Base64.Decode(
+            "MIGJAoGBAHNc+iExm94LUrJdPSJ4QJ9tDRuvaNmGVHpJ4X7a5zKI02v+2E7RotuiR2MHDJfVJkb9LUs2kb3XBlyENhtMLsbeH+3Muy3" +
+            "hGDlh/mLJSh1s4c5jDKBRYOHom7Uc8wP0P2+zBCA+OEdikNDFBaP5PbR2Xq9okG2kPh35M2quAiMTAgMBAAE=");
+
+        public override string Name
+        {
+            get { return "Asn1Integer"; }
+        }
+
+        public override void PerformTest()
+        {
+#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || (PORTABLE && !DOTNET) || NET_1_1
+            // Can't SetEnvironmentVariable !
+#else
+            SetAllowUnsafeProperty(true);
+
+            Asn1Sequence.GetInstance(suspectKey);
+
+            DoTestValidEncodingSingleByte();
+            DoTestValidEncodingMultiByte();
+            DoTestInvalidEncoding_00();
+            DoTestInvalidEncoding_ff();
+            DoTestInvalidEncoding_00_32bits();
+            DoTestInvalidEncoding_ff_32bits();
+            //DoDoTestLooseInvalidValidEncoding_FF_32B();
+            //DoTestLooseInvalidValidEncoding_zero_32B();
+            DoTestLooseValidEncoding_zero_32BAligned();
+            DoTestLooseValidEncoding_FF_32BAligned();
+            DoTestLooseValidEncoding_FF_32BAligned_1not0();
+            DoTestLooseValidEncoding_FF_32BAligned_2not0();
+            DoTestOversizedEncoding();
+
+            SetAllowUnsafeProperty(true);
+
+            new DerInteger(Hex.Decode("ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e"));
+
+            new DerEnumerated(Hex.Decode("ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e"));
+
+            SetAllowUnsafeProperty(false);
+
+            try
+            {
+                new DerInteger(Hex.Decode("ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b"));
+
+                Fail("no exception");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed integer", e.Message);
+            }
+
+            // No support for thread-local override in C# version
+            //IsTrue(!Properties.SetThreadOverride("org.bouncycastle.asn1.allow_unsafe_integer", true));
+
+            //new DerInteger(Hex.Decode("ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b"));
+
+            //IsTrue(Properties.RemoveThreadOverride("org.bouncycastle.asn1.allow_unsafe_integer"));
+
+            try
+            {
+                Asn1Sequence.GetInstance(suspectKey);
+
+                Fail("no exception");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("test 1", "failed to construct sequence from byte[]: corrupted stream detected", e.Message);
+            }
+
+            try
+            {
+                new DerInteger(Hex.Decode("ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e"));
+
+                Fail("no exception");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed integer", e.Message);
+            }
+
+            try
+            {
+                new DerEnumerated(Hex.Decode("ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e"));
+
+                Fail("no exception");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed enumerated", e.Message);
+            }
+#endif
+        }
+
+        /**
+         * Ensure existing single byte behavior.
+         */
+        public void DoTestValidEncodingSingleByte()
+        {
+            SetAllowUnsafeProperty(false);
+
+            //
+            // Without property, single byte.
+            //
+            byte[] rawInt = Hex.Decode("10");
+            DerInteger i = new DerInteger(rawInt);
+            IsEquals(i.Value.IntValue, 16);
+
+            //
+            // With property set.
+            //
+            SetAllowUnsafeProperty(true);
+
+            rawInt = Hex.Decode("10");
+            i = new DerInteger(rawInt);
+            IsEquals(i.Value.IntValue, 16);
+        }
+
+        public void DoTestValidEncodingMultiByte()
+        {
+            SetAllowUnsafeProperty(false);
+
+            //
+            // Without property, multi-byte.
+            //
+            byte[] rawInt = Hex.Decode("10FF");
+            DerInteger i = new DerInteger(rawInt);
+            IsEquals(i.Value.IntValue, 4351);
+
+            //
+            // With property set.
+            //
+            SetAllowUnsafeProperty(true);
+
+            rawInt = Hex.Decode("10FF");
+            i = new DerInteger(rawInt);
+            IsEquals(i.Value.IntValue, 4351);
+        }
+
+        public void DoTestInvalidEncoding_00()
+        {
+            SetAllowUnsafeProperty(false);
+            try
+            {
+                byte[] rawInt = Hex.Decode("0010FF");
+                DerInteger i = new DerInteger(rawInt);
+                IsEquals(i.Value.IntValue, 4351);
+                Fail("Expecting illegal argument exception.");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed integer", e.Message);
+            }
+        }
+
+        public void DoTestInvalidEncoding_ff()
+        {
+            SetAllowUnsafeProperty(false);
+
+            try
+            {
+                byte[] rawInt = Hex.Decode("FF81FF");
+                DerInteger i = new DerInteger(rawInt);
+                Fail("Expecting illegal argument exception.");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed integer", e.Message);
+            }
+        }
+
+        public void DoTestInvalidEncoding_00_32bits()
+        {
+            SetAllowUnsafeProperty(false);
+
+            //
+            // Check what would pass loose validation fails outside of loose validation.
+            //
+            try
+            {
+                byte[] rawInt = Hex.Decode("0000000010FF");
+                DerInteger i = new DerInteger(rawInt);
+                IsEquals(i.Value.IntValue, 4351);
+                Fail("Expecting illegal argument exception.");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed integer", e.Message);
+            }
+        }
+
+        public void DoTestInvalidEncoding_ff_32bits()
+        {
+            SetAllowUnsafeProperty(false);
+
+            //
+            // Check what would pass loose validation fails outside of loose validation.
+            //
+            try
+            {
+                byte[] rawInt = Hex.Decode("FFFFFFFF01FF");
+                DerInteger i = new DerInteger(rawInt);
+                Fail("Expecting illegal argument exception.");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed integer", e.Message);
+            }
+        }
+
+        /*
+         Unfortunately it turns out that integers stored without sign bits that are assumed to be
+         unsigned.. this means a string of FF may occur and then the user will call getPositiveValue().
+         Sigh..
+        public void DoTestLooseInvalidValidEncoding_zero_32B()
+            throws Exception
+        {
+            //
+            // Should still fail as loose validation only permits 3 leading 0x00 bytes.
+            //
+            try
+            {
+                SetAllowUnsafeProperty(true);
+                byte[] rawInt = Hex.Decode("0000000010FF");
+                DerInteger i = new DerInteger(rawInt);
+                Fail("Expecting illegal argument exception.");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed integer", e.Message);
+            }
+        }
+
+        public void DoDoTestLooseInvalidValidEncoding_FF_32B()
+            throws Exception
+        {
+            //
+            // Should still fail as loose validation only permits 3 leading 0xFF bytes.
+            //
+            try
+            {
+                SetAllowUnsafeProperty(true);
+                byte[] rawInt = Hex.Decode("FFFFFFFF10FF");
+                DerInteger i = new DerInteger(rawInt);
+                Fail("Expecting illegal argument exception.");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed integer", e.Message);
+            }
+        }
+        */
+
+        public void DoTestLooseValidEncoding_zero_32BAligned()
+        {
+            //
+            // Should pass as loose validation permits 3 leading 0x00 bytes.
+            //
+            SetAllowUnsafeProperty(true);
+            byte[] rawInt = Hex.Decode("00000010FF000000");
+            DerInteger i = new DerInteger(rawInt);
+            IsEquals(72997666816L, i.Value.LongValue);
+        }
+
+        public void DoTestLooseValidEncoding_FF_32BAligned()
+        {
+            //
+            // Should pass as loose validation permits 3 leading 0xFF bytes
+            //
+            SetAllowUnsafeProperty(true);
+            byte[] rawInt = Hex.Decode("FFFFFF10FF000000");
+            DerInteger i = new DerInteger(rawInt);
+            IsEquals(-1026513960960L, i.Value.LongValue);
+        }
+
+        public void DoTestLooseValidEncoding_FF_32BAligned_1not0()
+        {
+            //
+            // Should pass as loose validation permits 3 leading 0xFF bytes.
+            //
+            SetAllowUnsafeProperty(true);
+            byte[] rawInt = Hex.Decode("FFFEFF10FF000000");
+            DerInteger i = new DerInteger(rawInt);
+            IsEquals(-282501490671616L, i.Value.LongValue);
+        }
+
+        public void DoTestLooseValidEncoding_FF_32BAligned_2not0()
+        {
+            //
+            // Should pass as loose validation permits 3 leading 0xFF bytes.
+            //
+            SetAllowUnsafeProperty(true);
+            byte[] rawInt = Hex.Decode("FFFFFE10FF000000");
+            DerInteger i = new DerInteger(rawInt);
+            IsEquals(-2126025588736L, i.Value.LongValue);
+        }
+
+        public void DoTestOversizedEncoding()
+        {
+            //
+            // Should pass as loose validation permits 3 leading 0xFF bytes.
+            //
+            SetAllowUnsafeProperty(true);
+            byte[] rawInt = Hex.Decode("FFFFFFFE10FF000000000000");
+            DerInteger i = new DerInteger(rawInt);
+            IsEquals(new BigInteger(Hex.Decode("FFFFFFFE10FF000000000000")), i.Value);
+
+            rawInt = Hex.Decode("FFFFFFFFFE10FF000000000000");
+            try
+            {
+                new DerInteger(rawInt);
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed integer", e.Message);
+            }
+        }
+
+        private void SetAllowUnsafeProperty(bool allowUnsafe)
+        {
+#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || (PORTABLE && !DOTNET) || NET_1_1
+            // Can't SetEnvironmentVariable !
+#else
+            Environment.SetEnvironmentVariable(DerInteger.AllowUnsafeProperty, allowUnsafe ? "true" : "false");
+#endif
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new Asn1IntegerTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/crypto/test/src/asn1/test/RegressionTest.cs b/crypto/test/src/asn1/test/RegressionTest.cs
index eeca9ccd0..4534f2c75 100644
--- a/crypto/test/src/asn1/test/RegressionTest.cs
+++ b/crypto/test/src/asn1/test/RegressionTest.cs
@@ -11,6 +11,7 @@ namespace Org.BouncyCastle.Asn1.Tests
 			new AdditionalInformationSyntaxUnitTest(),
 			new AdmissionSyntaxUnitTest(),
 			new AdmissionsUnitTest(),
+            new Asn1IntegerTest(),
 			new AttributeTableUnitTest(),
             new BiometricDataUnitTest(),
             new BitStringTest(),