summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2015-04-18 21:22:01 +0700
committerJeffrey Stedfast <jeff@xamarin.com>2015-05-07 10:16:28 -0400
commit3ce61b5ebe84b928e1c067c0e2d5b0e53f834137 (patch)
treeecc67134e60456274094c4afff02284fa58fed39
parentRemove overly strict check on ECC extensions (diff)
downloadBouncyCastle.NET-ed25519-3ce61b5ebe84b928e1c067c0e2d5b0e53f834137.tar.xz
Port recent Java updates
-rw-r--r--crypto/BouncyCastle.Android.csproj4
-rw-r--r--crypto/BouncyCastle.csproj4
-rw-r--r--crypto/BouncyCastle.iOS.csproj4
-rw-r--r--crypto/crypto.csproj20
-rw-r--r--crypto/src/bcpg/ECDHPublicBCPGKey.cs102
-rw-r--r--crypto/src/bcpg/ECDsaPublicBCPGKey.cs34
-rw-r--r--crypto/src/bcpg/ECPublicBCPGKey.cs97
-rw-r--r--crypto/src/bcpg/ECSecretBCPGKey.cs56
-rw-r--r--crypto/src/bcpg/PublicKeyPacket.cs6
-rw-r--r--crypto/src/bcpg/SignaturePacket.cs5
-rw-r--r--crypto/src/crypto/modes/CcmBlockCipher.cs11
-rw-r--r--crypto/src/openpgp/PgpPublicKey.cs5
12 files changed, 343 insertions, 5 deletions
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index 05eef369d..51f7f19a2 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -486,6 +486,10 @@
     <Compile Include="src\bcpg\Crc24.cs" />
     <Compile Include="src\bcpg\DsaPublicBcpgKey.cs" />
     <Compile Include="src\bcpg\DsaSecretBcpgKey.cs" />
+    <Compile Include="src\bcpg\ECDHPublicBCPGKey.cs" />
+    <Compile Include="src\bcpg\ECDsaPublicBCPGKey.cs" />
+    <Compile Include="src\bcpg\ECPublicBCPGKey.cs" />
+    <Compile Include="src\bcpg\ECSecretBCPGKey.cs" />
     <Compile Include="src\bcpg\ElGamalPublicBcpgKey.cs" />
     <Compile Include="src\bcpg\ElGamalSecretBcpgKey.cs" />
     <Compile Include="src\bcpg\ExperimentalPacket.cs" />
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index 668648ccc..117af8d95 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -480,6 +480,10 @@
     <Compile Include="src\bcpg\Crc24.cs" />
     <Compile Include="src\bcpg\DsaPublicBcpgKey.cs" />
     <Compile Include="src\bcpg\DsaSecretBcpgKey.cs" />
+    <Compile Include="src\bcpg\ECDHPublicBCPGKey.cs" />
+    <Compile Include="src\bcpg\ECDsaPublicBCPGKey.cs" />
+    <Compile Include="src\bcpg\ECPublicBCPGKey.cs" />
+    <Compile Include="src\bcpg\ECSecretBCPGKey.cs" />
     <Compile Include="src\bcpg\ElGamalPublicBcpgKey.cs" />
     <Compile Include="src\bcpg\ElGamalSecretBcpgKey.cs" />
     <Compile Include="src\bcpg\ExperimentalPacket.cs" />
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index 372153436..a1d3b15a1 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -481,6 +481,10 @@
     <Compile Include="src\bcpg\Crc24.cs" />
     <Compile Include="src\bcpg\DsaPublicBcpgKey.cs" />
     <Compile Include="src\bcpg\DsaSecretBcpgKey.cs" />
+    <Compile Include="src\bcpg\ECDHPublicBCPGKey.cs" />
+    <Compile Include="src\bcpg\ECDsaPublicBCPGKey.cs" />
+    <Compile Include="src\bcpg\ECPublicBCPGKey.cs" />
+    <Compile Include="src\bcpg\ECSecretBCPGKey.cs" />
     <Compile Include="src\bcpg\ElGamalPublicBcpgKey.cs" />
     <Compile Include="src\bcpg\ElGamalSecretBcpgKey.cs" />
     <Compile Include="src\bcpg\ExperimentalPacket.cs" />
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index cb00f9912..0a0e2c1da 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -2324,6 +2324,26 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\bcpg\ECDHPublicBCPGKey.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\bcpg\ECDsaPublicBCPGKey.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\bcpg\ECPublicBCPGKey.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\bcpg\ECSecretBCPGKey.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\bcpg\ElGamalPublicBCPGKey.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/bcpg/ECDHPublicBCPGKey.cs b/crypto/src/bcpg/ECDHPublicBCPGKey.cs
new file mode 100644
index 000000000..b85379586
--- /dev/null
+++ b/crypto/src/bcpg/ECDHPublicBCPGKey.cs
@@ -0,0 +1,102 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <remarks>Base class for an ECDH Public Key.</remarks>
+    public class ECDHPublicBcpgKey
+        : ECPublicBcpgKey
+    {
+        private byte reserved;
+        private byte hashFunctionId;
+        private byte symAlgorithmId;
+
+        /// <param name="bcpgIn">The stream to read the packet from.</param>
+        public ECDHPublicBcpgKey(
+            BcpgInputStream bcpgIn)
+            : base(bcpgIn)
+        {
+            int length = bcpgIn.ReadByte();
+            byte[] kdfParameters =  new byte[length];
+            if (kdfParameters.Length != 3)
+                throw new InvalidOperationException("kdf parameters size of 3 expected.");
+
+            bcpgIn.ReadFully(kdfParameters);
+
+            reserved = kdfParameters[0];
+            hashFunctionId = kdfParameters[1];
+            symAlgorithmId = kdfParameters[2];
+
+            VerifyHashAlgorithm();
+            VerifySymmetricKeyAlgorithm();
+        }
+
+        public ECDHPublicBcpgKey(
+            DerObjectIdentifier oid,
+            ECPoint point,
+            int hashAlgorithm,
+            int symmetricKeyAlgorithm)
+            : base(oid, point)
+        {
+            reserved = 1;
+            hashFunctionId = (byte)hashAlgorithm;
+            symAlgorithmId = (byte)symmetricKeyAlgorithm;
+
+            VerifyHashAlgorithm();
+            VerifySymmetricKeyAlgorithm();
+        }
+
+        public virtual byte Reserved
+        {
+            get { return reserved; }
+        }
+
+        public virtual byte HashAlgorithm
+        {
+            get { return hashFunctionId; }
+        }
+
+        public virtual byte SymmetricKeyAlgorithm
+        {
+            get { return symAlgorithmId; }
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            base.Encode(bcpgOut);
+            bcpgOut.WriteByte(0x3);
+            bcpgOut.WriteByte(reserved);
+            bcpgOut.WriteByte(hashFunctionId);
+            bcpgOut.WriteByte(symAlgorithmId);
+        }
+
+        private void VerifyHashAlgorithm()
+        {
+            switch ((HashAlgorithmTag)hashFunctionId)
+            {
+            case HashAlgorithmTag.Sha256:
+            case HashAlgorithmTag.Sha384:
+            case HashAlgorithmTag.Sha512:
+                break;
+            default:
+                throw new InvalidOperationException("Hash algorithm must be SHA-256 or stronger.");
+            }
+        }
+
+        private void VerifySymmetricKeyAlgorithm()
+        {
+            switch ((SymmetricKeyAlgorithmTag)symAlgorithmId)
+            {
+            case SymmetricKeyAlgorithmTag.Aes128:
+            case SymmetricKeyAlgorithmTag.Aes192:
+            case SymmetricKeyAlgorithmTag.Aes256:
+                break;
+            default:
+                throw new InvalidOperationException("Symmetric key algorithm must be AES-128 or stronger.");
+            }
+        }
+    }
+}
diff --git a/crypto/src/bcpg/ECDsaPublicBCPGKey.cs b/crypto/src/bcpg/ECDsaPublicBCPGKey.cs
new file mode 100644
index 000000000..5f0c8ac55
--- /dev/null
+++ b/crypto/src/bcpg/ECDsaPublicBCPGKey.cs
@@ -0,0 +1,34 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <remarks>Base class for an ECDSA Public Key.</remarks>
+    public class ECDsaPublicBcpgKey
+        : ECPublicBcpgKey
+    {
+        /// <param name="bcpgIn">The stream to read the packet from.</param>
+        protected internal ECDsaPublicBcpgKey(
+            BcpgInputStream bcpgIn)
+            : base(bcpgIn)
+        {
+        }
+
+        public ECDsaPublicBcpgKey(
+            DerObjectIdentifier oid,
+            ECPoint point)
+            : base(oid, point)
+        {
+        }
+
+        public ECDsaPublicBcpgKey(
+            DerObjectIdentifier oid,
+            BigInteger encodedPoint)
+            : base(oid, encodedPoint)
+        {
+        }
+    }
+}
diff --git a/crypto/src/bcpg/ECPublicBCPGKey.cs b/crypto/src/bcpg/ECPublicBCPGKey.cs
new file mode 100644
index 000000000..f328f9dc3
--- /dev/null
+++ b/crypto/src/bcpg/ECPublicBCPGKey.cs
@@ -0,0 +1,97 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <remarks>Base class for an EC Public Key.</remarks>
+    public abstract class ECPublicBcpgKey
+        : BcpgObject, IBcpgKey
+    {
+        internal DerObjectIdentifier oid;
+        internal BigInteger point;
+
+        /// <param name="bcpgIn">The stream to read the packet from.</param>
+        protected ECPublicBcpgKey(
+            BcpgInputStream bcpgIn)
+        {
+            this.oid = DerObjectIdentifier.GetInstance(Asn1Object.FromByteArray(ReadBytesOfEncodedLength(bcpgIn)));
+            this.point = new MPInteger(bcpgIn).Value;
+        }
+
+        protected ECPublicBcpgKey(
+            DerObjectIdentifier oid,
+            ECPoint point)
+        {
+            this.point = new BigInteger(1, point.GetEncoded());
+            this.oid = oid;
+        }
+
+        protected ECPublicBcpgKey(
+            DerObjectIdentifier oid,
+            BigInteger encodedPoint)
+        {
+            this.point = encodedPoint;
+            this.oid = oid;
+        }
+
+        /// <summary>The format, as a string, always "PGP".</summary>
+        public string Format
+        {
+            get { return "PGP"; }
+        }
+
+        /// <summary>Return the standard PGP encoding of the key.</summary>
+        public override byte[] GetEncoded()
+        {
+            try
+            {
+                return base.GetEncoded();
+            }
+            catch (IOException)
+            {
+                return null;
+            }
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            byte[] oid = this.oid.GetEncoded();
+            bcpgOut.Write(oid, 1, oid.Length - 1);
+
+            MPInteger point = new MPInteger(this.point);
+            bcpgOut.WriteObject(point);
+        }
+
+        public virtual BigInteger EncodedPoint
+        {
+            get { return point; }
+        }
+
+        public virtual DerObjectIdentifier CurveOid
+        {
+            get { return oid; }
+        }
+
+        protected static byte[] ReadBytesOfEncodedLength(
+            BcpgInputStream bcpgIn)
+        {
+            int length = bcpgIn.ReadByte();
+            if (length == 0 || length == 0xFF)
+            {
+                throw new IOException("future extensions not yet implemented.");
+            }
+
+            byte[] buffer = new byte[length + 2];
+            bcpgIn.ReadFully(buffer, 2, buffer.Length - 2);
+            buffer[0] = (byte)0x06;
+            buffer[1] = (byte)length;
+
+            return buffer;
+        }
+    }
+}
diff --git a/crypto/src/bcpg/ECSecretBCPGKey.cs b/crypto/src/bcpg/ECSecretBCPGKey.cs
new file mode 100644
index 000000000..22e0a3473
--- /dev/null
+++ b/crypto/src/bcpg/ECSecretBCPGKey.cs
@@ -0,0 +1,56 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Base class for an EC Secret Key.</remarks>
+    public class ECSecretBcpgKey
+        : BcpgObject, IBcpgKey
+    {
+        internal MPInteger x;
+
+        public ECSecretBcpgKey(
+            BcpgInputStream bcpgIn)
+        {
+            this.x = new MPInteger(bcpgIn);
+        }
+
+        public ECSecretBcpgKey(
+            BigInteger x)
+        {
+            this.x = new MPInteger(x);
+        }
+
+		/// <summary>The format, as a string, always "PGP".</summary>
+		public string Format
+		{
+			get { return "PGP"; }
+		}
+
+		/// <summary>Return the standard PGP encoding of the key.</summary>
+		public override byte[] GetEncoded()
+		{
+			try
+			{
+				return base.GetEncoded();
+			}
+			catch (Exception)
+			{
+				return null;
+			}
+		}
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WriteObject(x);
+        }
+
+        public virtual BigInteger X
+        {
+            get { return x.Value; }
+        }
+    }
+}
diff --git a/crypto/src/bcpg/PublicKeyPacket.cs b/crypto/src/bcpg/PublicKeyPacket.cs
index a45aeb469..cea5c8ed2 100644
--- a/crypto/src/bcpg/PublicKeyPacket.cs
+++ b/crypto/src/bcpg/PublicKeyPacket.cs
@@ -44,6 +44,12 @@ namespace Org.BouncyCastle.Bcpg
                 case PublicKeyAlgorithmTag.ElGamalGeneral:
                     key = new ElGamalPublicBcpgKey(bcpgIn);
                     break;
+                case PublicKeyAlgorithmTag.EC:
+                    key = new ECDHPublicBcpgKey(bcpgIn);
+                    break;
+                case PublicKeyAlgorithmTag.ECDsa:
+                    key = new ECDsaPublicBcpgKey(bcpgIn);
+                    break;
                 default:
                     throw new IOException("unknown PGP public key algorithm encountered");
             }
diff --git a/crypto/src/bcpg/SignaturePacket.cs b/crypto/src/bcpg/SignaturePacket.cs
index 605ce84c4..5b91c15a3 100644
--- a/crypto/src/bcpg/SignaturePacket.cs
+++ b/crypto/src/bcpg/SignaturePacket.cs
@@ -146,6 +146,11 @@ namespace Org.BouncyCastle.Bcpg
                     MPInteger y = new MPInteger(bcpgIn);
 					signature = new MPInteger[]{ p, g, y };
                     break;
+                case PublicKeyAlgorithmTag.ECDsa:
+                    MPInteger ecR = new MPInteger(bcpgIn);
+                    MPInteger ecS = new MPInteger(bcpgIn);
+                    signature = new MPInteger[]{ ecR, ecS };
+                    break;
                 default:
 					if (keyAlgorithm >= PublicKeyAlgorithmTag.Experimental_1 && keyAlgorithm <= PublicKeyAlgorithmTag.Experimental_11)
 					{
diff --git a/crypto/src/crypto/modes/CcmBlockCipher.cs b/crypto/src/crypto/modes/CcmBlockCipher.cs
index e0b1e6b54..19e273d7c 100644
--- a/crypto/src/crypto/modes/CcmBlockCipher.cs
+++ b/crypto/src/crypto/modes/CcmBlockCipher.cs
@@ -268,9 +268,10 @@ namespace Org.BouncyCastle.Crypto.Modes
                 outputLen = inLen + macSize;
                 Check.OutputLength(output, outOff, outputLen, "Output buffer too short.");
 
-                calculateMac(input, inOff, inLen, macBlock);
+                CalculateMac(input, inOff, inLen, macBlock);
 
-                ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0);   // S0
+                byte[] encMac = new byte[BlockSize];
+                ctrCipher.ProcessBlock(macBlock, 0, encMac, 0);   // S0
 
                 while (inIndex < (inOff + inLen - BlockSize))                 // S1...
                 {
@@ -287,7 +288,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 Array.Copy(block, 0, output, outIndex, inLen + inOff - inIndex);
 
-                Array.Copy(macBlock, 0, output, outOff + inLen, macSize);
+                Array.Copy(encMac, 0, output, outOff + inLen, macSize);
             }
             else
             {
@@ -323,7 +324,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 byte[] calculatedMacBlock = new byte[BlockSize];
 
-                calculateMac(output, outOff, outputLen, calculatedMacBlock);
+                CalculateMac(output, outOff, outputLen, calculatedMacBlock);
 
                 if (!Arrays.ConstantTimeAreEqual(macBlock, calculatedMacBlock))
                     throw new InvalidCipherTextException("mac check in CCM failed");
@@ -332,7 +333,7 @@ namespace Org.BouncyCastle.Crypto.Modes
             return outputLen;
         }
 
-        private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
+        private int CalculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
         {
             IMac cMac = new CbcBlockCipherMac(cipher, macSize * 8);
 
diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs
index 249b94ea6..5bde2c8fe 100644
--- a/crypto/src/openpgp/PgpPublicKey.cs
+++ b/crypto/src/openpgp/PgpPublicKey.cs
@@ -2,6 +2,7 @@ using System;
 using System.Collections;
 using System.IO;
 
+using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.IO;
 using Org.BouncyCastle.Crypto.Parameters;
@@ -104,6 +105,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 {
                     this.keyStrength = ((ElGamalPublicBcpgKey)key).P.BitLength;
                 }
+                else if (key is ECPublicBcpgKey)
+                {
+                    this.keyStrength = ECNamedCurveTable.GetByOid(((ECPublicBcpgKey)key).CurveOid).Curve.FieldSize;
+                }
             }
         }