summary refs log tree commit diff
path: root/Crypto/src/crypto/agreement/kdf
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/agreement/kdf')
-rw-r--r--Crypto/src/crypto/agreement/kdf/DHKdfParameters.cs57
-rw-r--r--Crypto/src/crypto/agreement/kdf/DHKekGenerator.cs129
-rw-r--r--Crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs71
3 files changed, 257 insertions, 0 deletions
diff --git a/Crypto/src/crypto/agreement/kdf/DHKdfParameters.cs b/Crypto/src/crypto/agreement/kdf/DHKdfParameters.cs
new file mode 100644
index 000000000..f6c9e6079
--- /dev/null
+++ b/Crypto/src/crypto/agreement/kdf/DHKdfParameters.cs
@@ -0,0 +1,57 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Kdf
+{
+	public class DHKdfParameters
+		: IDerivationParameters
+	{
+		private readonly DerObjectIdentifier algorithm;
+		private readonly int keySize;
+		private readonly byte[] z;
+		private readonly byte[] extraInfo;
+
+		public DHKdfParameters(
+			DerObjectIdentifier	algorithm,
+			int					keySize,
+			byte[]				z)
+			: this(algorithm, keySize, z, null)
+		{
+		}
+
+		public DHKdfParameters(
+			DerObjectIdentifier algorithm,
+			int keySize,
+			byte[] z,
+			byte[] extraInfo)
+		{
+			this.algorithm = algorithm;
+			this.keySize = keySize;
+			this.z = z; // TODO Clone?
+			this.extraInfo = extraInfo;
+		}
+
+		public DerObjectIdentifier Algorithm
+		{
+			get { return algorithm; }
+		}
+
+		public int KeySize
+		{
+			get { return keySize; }
+		}
+
+		public byte[] GetZ()
+		{
+			// TODO Clone?
+			return z;
+		}
+
+		public byte[] GetExtraInfo()
+		{
+			// TODO Clone?
+			return extraInfo;
+		}
+	}
+}
diff --git a/Crypto/src/crypto/agreement/kdf/DHKekGenerator.cs b/Crypto/src/crypto/agreement/kdf/DHKekGenerator.cs
new file mode 100644
index 000000000..fa2921539
--- /dev/null
+++ b/Crypto/src/crypto/agreement/kdf/DHKekGenerator.cs
@@ -0,0 +1,129 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Kdf
+{
+	/**
+	* RFC 2631 Diffie-hellman KEK derivation function.
+	*/
+	public class DHKekGenerator
+		: IDerivationFunction
+	{
+		private readonly IDigest digest;
+
+		private DerObjectIdentifier	algorithm;
+		private int					keySize;
+		private byte[]				z;
+		private byte[]				partyAInfo;
+
+		public DHKekGenerator(
+			IDigest digest)
+		{
+			this.digest = digest;
+		}
+
+		public void Init(
+			IDerivationParameters param)
+		{
+			DHKdfParameters parameters = (DHKdfParameters)param;
+
+			this.algorithm = parameters.Algorithm;
+			this.keySize = parameters.KeySize;
+			this.z = parameters.GetZ(); // TODO Clone?
+			this.partyAInfo = parameters.GetExtraInfo(); // TODO Clone?
+		}
+
+		public IDigest Digest
+		{
+			get { return digest; }
+		}
+
+		public int GenerateBytes(
+			byte[]	outBytes,
+			int		outOff,
+			int		len)
+		{
+			if ((outBytes.Length - len) < outOff)
+			{
+				throw new DataLengthException("output buffer too small");
+			}
+
+			long oBytes = len;
+			int outLen = digest.GetDigestSize();
+
+			//
+			// this is at odds with the standard implementation, the
+			// maximum value should be hBits * (2^32 - 1) where hBits
+			// is the digest output size in bits. We can't have an
+			// array with a long index at the moment...
+			//
+			if (oBytes > ((2L << 32) - 1))
+			{
+				throw new ArgumentException("Output length too large");
+			}
+
+			int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+
+			byte[] dig = new byte[digest.GetDigestSize()];
+
+			int counter = 1;
+
+			for (int i = 0; i < cThreshold; i++)
+			{
+				digest.BlockUpdate(z, 0, z.Length);
+
+				// KeySpecificInfo
+				DerSequence keyInfo = new DerSequence(
+					algorithm,
+					new DerOctetString(integerToBytes(counter)));
+
+				// OtherInfo
+				Asn1EncodableVector v1 = new Asn1EncodableVector(keyInfo);
+
+				if (partyAInfo != null)
+				{
+					v1.Add(new DerTaggedObject(true, 0, new DerOctetString(partyAInfo)));
+				}
+
+				v1.Add(new DerTaggedObject(true, 2, new DerOctetString(integerToBytes(keySize))));
+
+				byte[] other = new DerSequence(v1).GetDerEncoded();
+
+				digest.BlockUpdate(other, 0, other.Length);
+
+				digest.DoFinal(dig, 0);
+
+				if (len > outLen)
+				{
+					Array.Copy(dig, 0, outBytes, outOff, outLen);
+					outOff += outLen;
+					len -= outLen;
+				}
+				else
+				{
+					Array.Copy(dig, 0, outBytes, outOff, len);
+				}
+
+				counter++;
+			}
+
+			digest.Reset();
+
+			return len;
+		}
+
+		private byte[] integerToBytes(
+			int keySize)
+		{
+			byte[] val = new byte[4];
+
+			val[0] = (byte)(keySize >> 24);
+			val[1] = (byte)(keySize >> 16);
+			val[2] = (byte)(keySize >> 8);
+			val[3] = (byte)keySize;
+
+			return val;
+		}
+	}
+}
diff --git a/Crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs b/Crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs
new file mode 100644
index 000000000..7d55aa485
--- /dev/null
+++ b/Crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs
@@ -0,0 +1,71 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Kdf
+{
+	/**
+	* X9.63 based key derivation function for ECDH CMS.
+	*/
+	public class ECDHKekGenerator
+		: IDerivationFunction
+	{
+		private readonly IDerivationFunction kdf;
+
+		private DerObjectIdentifier	algorithm;
+		private int					keySize;
+		private byte[]				z;
+
+		public ECDHKekGenerator(
+			IDigest digest)
+		{
+			this.kdf = new Kdf2BytesGenerator(digest);
+		}
+
+		public void Init(
+			IDerivationParameters param)
+		{
+			DHKdfParameters parameters = (DHKdfParameters)param;
+
+			this.algorithm = parameters.Algorithm;
+			this.keySize = parameters.KeySize;
+			this.z = parameters.GetZ(); // TODO Clone?
+		}
+
+		public IDigest Digest
+		{
+			get { return kdf.Digest; }
+		}
+
+		public int GenerateBytes(
+			byte[]	outBytes,
+			int		outOff,
+			int		len)
+		{
+			// TODO Create an ASN.1 class for this (RFC3278)
+			// ECC-CMS-SharedInfo
+			DerSequence s = new DerSequence(
+				new AlgorithmIdentifier(algorithm, DerNull.Instance),
+				new DerTaggedObject(true, 2, new DerOctetString(integerToBytes(keySize))));
+
+			kdf.Init(new KdfParameters(z, s.GetDerEncoded()));
+
+			return kdf.GenerateBytes(outBytes, outOff, len);
+		}
+
+		private byte[] integerToBytes(int keySize)
+		{
+			byte[] val = new byte[4];
+
+			val[0] = (byte)(keySize >> 24);
+			val[1] = (byte)(keySize >> 16);
+			val[2] = (byte)(keySize >> 8);
+			val[3] = (byte)keySize;
+
+			return val;
+		}
+	}
+}