diff --git a/crypto/src/crypto/ec/CustomNamedCurves.cs b/crypto/src/crypto/ec/CustomNamedCurves.cs
new file mode 100644
index 000000000..ab609fdb9
--- /dev/null
+++ b/crypto/src/crypto/ec/CustomNamedCurves.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Crypto.EC
+{
+ public sealed class CustomNamedCurves
+ {
+ private CustomNamedCurves()
+ {
+ }
+
+ private static ECCurve ConfigureCurve(ECCurve curve)
+ {
+ return curve;
+ }
+
+ private static readonly IDictionary objIds = Platform.CreateHashtable();
+ private static readonly IDictionary curves = Platform.CreateHashtable();
+ private static readonly IDictionary names = Platform.CreateHashtable();
+
+ private static void DefineCurve(
+ string name,
+ DerObjectIdentifier oid,
+ X9ECParametersHolder holder)
+ {
+ objIds.Add(name, oid);
+ names.Add(oid, name);
+ curves.Add(oid, holder);
+ }
+
+ static CustomNamedCurves()
+ {
+ }
+
+ public static X9ECParameters GetByName(
+ string name)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier)
+ objIds[Platform.ToLowerInvariant(name)];
+
+ return oid == null ? null : GetByOid(oid);
+ }
+
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters GetByOid(
+ DerObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)curves[oid];
+
+ return holder == null ? null : holder.Parameters;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static DerObjectIdentifier GetOid(
+ string name)
+ {
+ return (DerObjectIdentifier)objIds[Platform.ToLowerInvariant(name)];
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static string GetName(
+ DerObjectIdentifier oid)
+ {
+ return (string)names[oid];
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static IEnumerable Names
+ {
+ get { return new EnumerableProxy(objIds.Keys); }
+ }
+ }
+}
diff --git a/crypto/src/crypto/engines/ChaChaEngine.cs b/crypto/src/crypto/engines/ChaChaEngine.cs
new file mode 100644
index 000000000..f4a7b8fe1
--- /dev/null
+++ b/crypto/src/crypto/engines/ChaChaEngine.cs
@@ -0,0 +1,189 @@
+using System;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+ /// <summary>
+ /// Implementation of Daniel J. Bernstein's ChaCha stream cipher.
+ /// </summary>
+ public class ChaChaEngine
+ : Salsa20Engine
+ {
+
+ /// <summary>
+ /// Creates a 20 rounds ChaCha engine.
+ /// </summary>
+ public ChaChaEngine()
+ {
+ }
+
+ /// <summary>
+ /// Creates a ChaCha engine with a specific number of rounds.
+ /// </summary>
+ /// <param name="rounds">the number of rounds (must be an even number).</param>
+ public ChaChaEngine(int rounds)
+ : base(rounds)
+ {
+ }
+
+ public override string AlgorithmName
+ {
+ get { return "ChaCha" + rounds; }
+ }
+
+ protected override void AdvanceCounter()
+ {
+ if (++engineState[12] == 0)
+ {
+ ++engineState[13];
+ }
+ }
+
+ protected override void ResetCounter()
+ {
+ engineState[12] = engineState[13] = 0;
+ }
+
+ protected override void SetKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ if ((keyBytes.Length != 16) && (keyBytes.Length != 32))
+ {
+ throw new ArgumentException(AlgorithmName + " requires 128 bit or 256 bit key");
+ }
+
+ int offset = 0;
+ byte[] constants;
+
+ // Key
+ engineState[4] = Pack.LE_To_UInt32(keyBytes, 0);
+ engineState[5] = Pack.LE_To_UInt32(keyBytes, 4);
+ engineState[6] = Pack.LE_To_UInt32(keyBytes, 8);
+ engineState[7] = Pack.LE_To_UInt32(keyBytes, 12);
+
+ if (keyBytes.Length == 32)
+ {
+ constants = sigma;
+ offset = 16;
+ } else
+ {
+ constants = tau;
+ }
+
+ engineState[8] = Pack.LE_To_UInt32(keyBytes, offset);
+ engineState[9] = Pack.LE_To_UInt32(keyBytes, offset + 4);
+ engineState[10] = Pack.LE_To_UInt32(keyBytes, offset + 8);
+ engineState[11] = Pack.LE_To_UInt32(keyBytes, offset + 12);
+
+ engineState[0] = Pack.LE_To_UInt32(constants, 0);
+ engineState[1] = Pack.LE_To_UInt32(constants, 4);
+ engineState[2] = Pack.LE_To_UInt32(constants, 8);
+ engineState[3] = Pack.LE_To_UInt32(constants, 12);
+
+ // Counter
+ engineState[12] = engineState[13] = 0;
+
+ // IV
+ engineState[14] = Pack.LE_To_UInt32(ivBytes, 0);
+ engineState[15] = Pack.LE_To_UInt32(ivBytes, 4);
+ }
+
+ protected override void GenerateKeyStream(byte[] output)
+ {
+ ChachaCore(rounds, engineState, x);
+ Pack.UInt32_To_LE(x, output, 0);
+ }
+
+ /// <summary>
+ /// ChacCha function.
+ /// </summary>
+ /// <param name="rounds">The number of ChaCha rounds to execute</param>
+ /// <param name="input">The input words.</param>
+ /// <param name="x">The ChaCha state to modify.</param>
+ internal static void ChachaCore(int rounds, uint[] input, uint[] x)
+ {
+ if (input.Length != 16) {
+ throw new ArgumentException();
+ }
+ if (x.Length != 16) {
+ throw new ArgumentException();
+ }
+ if (rounds % 2 != 0) {
+ throw new ArgumentException("Number of rounds must be even");
+ }
+
+ uint x00 = input[ 0];
+ uint x01 = input[ 1];
+ uint x02 = input[ 2];
+ uint x03 = input[ 3];
+ uint x04 = input[ 4];
+ uint x05 = input[ 5];
+ uint x06 = input[ 6];
+ uint x07 = input[ 7];
+ uint x08 = input[ 8];
+ uint x09 = input[ 9];
+ uint x10 = input[10];
+ uint x11 = input[11];
+ uint x12 = input[12];
+ uint x13 = input[13];
+ uint x14 = input[14];
+ uint x15 = input[15];
+
+ for (int i = rounds; i > 0; i -= 2)
+ {
+ x00 += x04; x12 = R(x12 ^ x00, 16);
+ x08 += x12; x04 = R(x04 ^ x08, 12);
+ x00 += x04; x12 = R(x12 ^ x00, 8);
+ x08 += x12; x04 = R(x04 ^ x08, 7);
+ x01 += x05; x13 = R(x13 ^ x01, 16);
+ x09 += x13; x05 = R(x05 ^ x09, 12);
+ x01 += x05; x13 = R(x13 ^ x01, 8);
+ x09 += x13; x05 = R(x05 ^ x09, 7);
+ x02 += x06; x14 = R(x14 ^ x02, 16);
+ x10 += x14; x06 = R(x06 ^ x10, 12);
+ x02 += x06; x14 = R(x14 ^ x02, 8);
+ x10 += x14; x06 = R(x06 ^ x10, 7);
+ x03 += x07; x15 = R(x15 ^ x03, 16);
+ x11 += x15; x07 = R(x07 ^ x11, 12);
+ x03 += x07; x15 = R(x15 ^ x03, 8);
+ x11 += x15; x07 = R(x07 ^ x11, 7);
+ x00 += x05; x15 = R(x15 ^ x00, 16);
+ x10 += x15; x05 = R(x05 ^ x10, 12);
+ x00 += x05; x15 = R(x15 ^ x00, 8);
+ x10 += x15; x05 = R(x05 ^ x10, 7);
+ x01 += x06; x12 = R(x12 ^ x01, 16);
+ x11 += x12; x06 = R(x06 ^ x11, 12);
+ x01 += x06; x12 = R(x12 ^ x01, 8);
+ x11 += x12; x06 = R(x06 ^ x11, 7);
+ x02 += x07; x13 = R(x13 ^ x02, 16);
+ x08 += x13; x07 = R(x07 ^ x08, 12);
+ x02 += x07; x13 = R(x13 ^ x02, 8);
+ x08 += x13; x07 = R(x07 ^ x08, 7);
+ x03 += x04; x14 = R(x14 ^ x03, 16);
+ x09 += x14; x04 = R(x04 ^ x09, 12);
+ x03 += x04; x14 = R(x14 ^ x03, 8);
+ x09 += x14; x04 = R(x04 ^ x09, 7);
+
+ }
+
+ x[ 0] = x00 + input[ 0];
+ x[ 1] = x01 + input[ 1];
+ x[ 2] = x02 + input[ 2];
+ x[ 3] = x03 + input[ 3];
+ x[ 4] = x04 + input[ 4];
+ x[ 5] = x05 + input[ 5];
+ x[ 6] = x06 + input[ 6];
+ x[ 7] = x07 + input[ 7];
+ x[ 8] = x08 + input[ 8];
+ x[ 9] = x09 + input[ 9];
+ x[10] = x10 + input[10];
+ x[11] = x11 + input[11];
+ x[12] = x12 + input[12];
+ x[13] = x13 + input[13];
+ x[14] = x14 + input[14];
+ x[15] = x15 + input[15];
+ }
+
+ }
+
+}
+
diff --git a/crypto/src/crypto/engines/IdeaEngine.cs b/crypto/src/crypto/engines/IdeaEngine.cs
index f763c5939..46b5a787c 100644
--- a/crypto/src/crypto/engines/IdeaEngine.cs
+++ b/crypto/src/crypto/engines/IdeaEngine.cs
@@ -1,5 +1,3 @@
-#if INCLUDE_IDEA
-
using System;
using Org.BouncyCastle.Crypto.Parameters;
@@ -12,26 +10,26 @@ namespace Org.BouncyCastle.Crypto.Engines
* This implementation is based on the "HOWTO: INTERNATIONAL DATA ENCRYPTION ALGORITHM"
* implementation summary by Fauzan Mirza (F.U.Mirza@sheffield.ac.uk). (baring 1 typo at the
* end of the mulinv function!).
- * </p>
+ * </p>
* <p>
* It can be found at ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/idea/
- * </p>
+ * </p>
* <p>
- * Note 1: This algorithm is patented in the USA, Japan, and Europe including
+ * Note 1: This algorithm is patented in the USA, Japan, and Europe including
* at least Austria, France, Germany, Italy, Netherlands, Spain, Sweden, Switzerland
* and the United Kingdom. Non-commercial use is free, however any commercial
* products are liable for royalties. Please see
* <a href="http://www.mediacrypt.com">www.mediacrypt.com</a> for
* further details. This announcement has been included at the request of
* the patent holders.
- * </p>
- * <p>
- * Note 2: Due to the requests concerning the above, this algorithm is now only
- * included in the extended assembly. It is not included in the default distributions.
- * </p>
+ * </p>
+ * <p>
+ * Note 2: Due to the requests concerning the above, this algorithm is now only
+ * included in the extended assembly. It is not included in the default distributions.
+ * </p>
*/
public class IdeaEngine
- : IBlockCipher
+ : IBlockCipher
{
private const int BLOCK_SIZE = 8;
private int[] workingKey;
@@ -54,28 +52,28 @@ namespace Org.BouncyCastle.Crypto.Engines
ICipherParameters parameters)
{
if (!(parameters is KeyParameter))
- throw new ArgumentException("invalid parameter passed to IDEA init - " + parameters.GetType().ToString());
+ throw new ArgumentException("invalid parameter passed to IDEA init - " + parameters.GetType().ToString());
- workingKey = GenerateWorkingKey(forEncryption,
- ((KeyParameter)parameters).GetKey());
+ workingKey = GenerateWorkingKey(forEncryption,
+ ((KeyParameter)parameters).GetKey());
}
- public string AlgorithmName
+ public string AlgorithmName
{
get { return "IDEA"; }
}
- public bool IsPartialBlockOkay
- {
- get { return false; }
- }
+ public bool IsPartialBlockOkay
+ {
+ get { return false; }
+ }
- public int GetBlockSize()
+ public int GetBlockSize()
{
return BLOCK_SIZE;
}
- public int ProcessBlock(
+ public int ProcessBlock(
byte[] input,
int inOff,
byte[] output,
@@ -228,7 +226,7 @@ namespace Org.BouncyCastle.Crypto.Engines
* Common Divisor algorithm. Zero and one are self inverse.
* <p>
* i.e. x * MulInv(x) == 1 (modulo BASE)
- * </p>
+ * </p>
*/
private int MulInv(
int x)
@@ -261,7 +259,7 @@ namespace Org.BouncyCastle.Crypto.Engines
* Return the additive inverse of x.
* <p>
* i.e. x + AddInv(x) == 0
- * </p>
+ * </p>
*/
int AddInv(
int x)
@@ -337,5 +335,3 @@ namespace Org.BouncyCastle.Crypto.Engines
}
}
}
-
-#endif
diff --git a/crypto/src/crypto/engines/Salsa20Engine.cs b/crypto/src/crypto/engines/Salsa20Engine.cs
index 7d68deab1..81884d603 100644
--- a/crypto/src/crypto/engines/Salsa20Engine.cs
+++ b/crypto/src/crypto/engines/Salsa20Engine.cs
@@ -7,44 +7,60 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Engines
{
- /**
- * Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
- */
+ /// <summary>
+ /// Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
+ /// </summary>
public class Salsa20Engine
: IStreamCipher
{
+ public static readonly int DEFAULT_ROUNDS = 20;
+
/** Constants */
private const int StateSize = 16; // 16, 32 bit ints = 64 bytes
- private readonly static byte[]
+ protected readonly static byte[]
sigma = Strings.ToAsciiByteArray("expand 32-byte k"),
tau = Strings.ToAsciiByteArray("expand 16-byte k");
+ protected int rounds;
+
/*
* variables to hold the state of the engine
* during encryption and decryption
*/
- private int index = 0;
- private uint[] engineState = new uint[StateSize]; // state
- private uint[] x = new uint[StateSize]; // internal buffer
- private byte[] keyStream = new byte[StateSize * 4], // expanded state, 64 bytes
- workingKey = null,
- workingIV = null;
- private bool initialised = false;
+ private int index = 0;
+ internal uint[] engineState = new uint[StateSize]; // state
+ internal uint[] x = new uint[StateSize]; // internal buffer
+ private byte[] keyStream = new byte[StateSize * 4]; // expanded state, 64 bytes
+ private bool initialised = false;
/*
* internal counter
*/
private uint cW0, cW1, cW2;
- /**
- * initialise a Salsa20 cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception ArgumentException if the params argument is
- * inappropriate.
- */
+ /// <summary>
+ /// Creates a 20 round Salsa20 engine.
+ /// </summary>
+ public Salsa20Engine()
+ : this(DEFAULT_ROUNDS)
+ {
+ }
+
+ /// <summary>
+ /// Creates a Salsa20 engine with a specific number of rounds.
+ /// </summary>
+ /// <param name="rounds">the number of rounds (must be an even number).</param>
+ public Salsa20Engine(int rounds)
+ {
+ if (rounds <= 0 || (rounds & 1) != 0)
+ {
+ throw new ArgumentException("'rounds' must be a positive, even number");
+ }
+
+ this.rounds = rounds;
+ }
+
public void Init(
bool forEncryption,
ICipherParameters parameters)
@@ -58,27 +74,38 @@ namespace Org.BouncyCastle.Crypto.Engines
ParametersWithIV ivParams = parameters as ParametersWithIV;
if (ivParams == null)
- throw new ArgumentException("Salsa20 Init requires an IV", "parameters");
+ throw new ArgumentException(AlgorithmName + " Init requires an IV", "parameters");
byte[] iv = ivParams.GetIV();
- if (iv == null || iv.Length != 8)
- throw new ArgumentException("Salsa20 requires exactly 8 bytes of IV");
+ if (iv == null || iv.Length != NonceSize)
+ throw new ArgumentException(AlgorithmName + " requires exactly " + NonceSize + " bytes of IV");
KeyParameter key = ivParams.Parameters as KeyParameter;
if (key == null)
- throw new ArgumentException("Salsa20 Init requires a key", "parameters");
+ throw new ArgumentException(AlgorithmName + " Init requires a key", "parameters");
- workingKey = key.GetKey();
- workingIV = iv;
+ SetKey(key.GetKey(), iv);
+ Reset();
+ initialised = true;
+ }
- SetKey(workingKey, workingIV);
+ protected virtual int NonceSize
+ {
+ get { return 8; }
}
- public string AlgorithmName
+ public virtual string AlgorithmName
{
- get { return "Salsa20"; }
+ get {
+ string name = "Salsa20";
+ if (rounds != DEFAULT_ROUNDS)
+ {
+ name += "/" + rounds;
+ }
+ return name;
+ }
}
public byte ReturnByte(
@@ -92,11 +119,7 @@ namespace Org.BouncyCastle.Crypto.Engines
if (index == 0)
{
GenerateKeyStream(keyStream);
-
- if (++engineState[8] == 0)
- {
- ++engineState[9];
- }
+ AdvanceCounter();
}
byte output = (byte)(keyStream[index] ^ input);
@@ -105,6 +128,14 @@ namespace Org.BouncyCastle.Crypto.Engines
return output;
}
+ protected virtual void AdvanceCounter()
+ {
+ if (++engineState[8] == 0)
+ {
+ ++engineState[9];
+ }
+ }
+
public void ProcessBytes(
byte[] inBytes,
int inOff,
@@ -137,11 +168,7 @@ namespace Org.BouncyCastle.Crypto.Engines
if (index == 0)
{
GenerateKeyStream(keyStream);
-
- if (++engineState[8] == 0)
- {
- ++engineState[9];
- }
+ AdvanceCounter();
}
outBytes[i+outOff] = (byte)(keyStream[index]^inBytes[i+inOff]);
index = (index + 1) & 63;
@@ -150,28 +177,32 @@ namespace Org.BouncyCastle.Crypto.Engines
public void Reset()
{
- SetKey(workingKey, workingIV);
+ index = 0;
+ ResetLimitCounter();
+ ResetCounter();
}
- // Private implementation
+ protected virtual void ResetCounter()
+ {
+ engineState[8] = engineState[9] = 0;
+ }
- private void SetKey(byte[] keyBytes, byte[] ivBytes)
+ protected virtual void SetKey(byte[] keyBytes, byte[] ivBytes)
{
- workingKey = keyBytes;
- workingIV = ivBytes;
+ if ((keyBytes.Length != 16) && (keyBytes.Length != 32)) {
+ throw new ArgumentException(AlgorithmName + " requires 128 bit or 256 bit key");
+ }
- index = 0;
- ResetCounter();
int offset = 0;
byte[] constants;
// Key
- engineState[1] = Pack.LE_To_UInt32(workingKey, 0);
- engineState[2] = Pack.LE_To_UInt32(workingKey, 4);
- engineState[3] = Pack.LE_To_UInt32(workingKey, 8);
- engineState[4] = Pack.LE_To_UInt32(workingKey, 12);
+ engineState[1] = Pack.LE_To_UInt32(keyBytes, 0);
+ engineState[2] = Pack.LE_To_UInt32(keyBytes, 4);
+ engineState[3] = Pack.LE_To_UInt32(keyBytes, 8);
+ engineState[4] = Pack.LE_To_UInt32(keyBytes, 12);
- if (workingKey.Length == 32)
+ if (keyBytes.Length == 32)
{
constants = sigma;
offset = 16;
@@ -181,83 +212,125 @@ namespace Org.BouncyCastle.Crypto.Engines
constants = tau;
}
- engineState[11] = Pack.LE_To_UInt32(workingKey, offset);
- engineState[12] = Pack.LE_To_UInt32(workingKey, offset + 4);
- engineState[13] = Pack.LE_To_UInt32(workingKey, offset + 8);
- engineState[14] = Pack.LE_To_UInt32(workingKey, offset + 12);
+ engineState[11] = Pack.LE_To_UInt32(keyBytes, offset);
+ engineState[12] = Pack.LE_To_UInt32(keyBytes, offset + 4);
+ engineState[13] = Pack.LE_To_UInt32(keyBytes, offset + 8);
+ engineState[14] = Pack.LE_To_UInt32(keyBytes, offset + 12);
engineState[0] = Pack.LE_To_UInt32(constants, 0);
engineState[5] = Pack.LE_To_UInt32(constants, 4);
engineState[10] = Pack.LE_To_UInt32(constants, 8);
engineState[15] = Pack.LE_To_UInt32(constants, 12);
// IV
- engineState[6] = Pack.LE_To_UInt32(workingIV, 0);
- engineState[7] = Pack.LE_To_UInt32(workingIV, 4);
- engineState[8] = engineState[9] = 0;
-
- initialised = true;
+ engineState[6] = Pack.LE_To_UInt32(ivBytes, 0);
+ engineState[7] = Pack.LE_To_UInt32(ivBytes, 4);
+ ResetCounter();
}
- private void GenerateKeyStream(byte[] output)
+ protected virtual void GenerateKeyStream(byte[] output)
{
- SalsaCore(20, engineState, x);
+ SalsaCore(rounds, engineState, x);
Pack.UInt32_To_LE(x, output, 0);
}
- internal static void SalsaCore(int rounds, uint[] state, uint[] x)
+ internal static void SalsaCore(int rounds, uint[] input, uint[] x)
{
- // TODO Exception if rounds odd?
+ if (input.Length != 16) {
+ throw new ArgumentException();
+ }
+ if (x.Length != 16) {
+ throw new ArgumentException();
+ }
+ if (rounds % 2 != 0) {
+ throw new ArgumentException("Number of rounds must be even");
+ }
- Array.Copy(state, 0, x, 0, state.Length);
+ uint x00 = input[ 0];
+ uint x01 = input[ 1];
+ uint x02 = input[ 2];
+ uint x03 = input[ 3];
+ uint x04 = input[ 4];
+ uint x05 = input[ 5];
+ uint x06 = input[ 6];
+ uint x07 = input[ 7];
+ uint x08 = input[ 8];
+ uint x09 = input[ 9];
+ uint x10 = input[10];
+ uint x11 = input[11];
+ uint x12 = input[12];
+ uint x13 = input[13];
+ uint x14 = input[14];
+ uint x15 = input[15];
for (int i = rounds; i > 0; i -= 2)
{
- x[ 4] ^= R((x[ 0]+x[12]), 7);
- x[ 8] ^= R((x[ 4]+x[ 0]), 9);
- x[12] ^= R((x[ 8]+x[ 4]),13);
- x[ 0] ^= R((x[12]+x[ 8]),18);
- x[ 9] ^= R((x[ 5]+x[ 1]), 7);
- x[13] ^= R((x[ 9]+x[ 5]), 9);
- x[ 1] ^= R((x[13]+x[ 9]),13);
- x[ 5] ^= R((x[ 1]+x[13]),18);
- x[14] ^= R((x[10]+x[ 6]), 7);
- x[ 2] ^= R((x[14]+x[10]), 9);
- x[ 6] ^= R((x[ 2]+x[14]),13);
- x[10] ^= R((x[ 6]+x[ 2]),18);
- x[ 3] ^= R((x[15]+x[11]), 7);
- x[ 7] ^= R((x[ 3]+x[15]), 9);
- x[11] ^= R((x[ 7]+x[ 3]),13);
- x[15] ^= R((x[11]+x[ 7]),18);
- x[ 1] ^= R((x[ 0]+x[ 3]), 7);
- x[ 2] ^= R((x[ 1]+x[ 0]), 9);
- x[ 3] ^= R((x[ 2]+x[ 1]),13);
- x[ 0] ^= R((x[ 3]+x[ 2]),18);
- x[ 6] ^= R((x[ 5]+x[ 4]), 7);
- x[ 7] ^= R((x[ 6]+x[ 5]), 9);
- x[ 4] ^= R((x[ 7]+x[ 6]),13);
- x[ 5] ^= R((x[ 4]+x[ 7]),18);
- x[11] ^= R((x[10]+x[ 9]), 7);
- x[ 8] ^= R((x[11]+x[10]), 9);
- x[ 9] ^= R((x[ 8]+x[11]),13);
- x[10] ^= R((x[ 9]+x[ 8]),18);
- x[12] ^= R((x[15]+x[14]), 7);
- x[13] ^= R((x[12]+x[15]), 9);
- x[14] ^= R((x[13]+x[12]),13);
- x[15] ^= R((x[14]+x[13]),18);
+ x04 ^= R((x00+x12), 7);
+ x08 ^= R((x04+x00), 9);
+ x12 ^= R((x08+x04),13);
+ x00 ^= R((x12+x08),18);
+ x09 ^= R((x05+x01), 7);
+ x13 ^= R((x09+x05), 9);
+ x01 ^= R((x13+x09),13);
+ x05 ^= R((x01+x13),18);
+ x14 ^= R((x10+x06), 7);
+ x02 ^= R((x14+x10), 9);
+ x06 ^= R((x02+x14),13);
+ x10 ^= R((x06+x02),18);
+ x03 ^= R((x15+x11), 7);
+ x07 ^= R((x03+x15), 9);
+ x11 ^= R((x07+x03),13);
+ x15 ^= R((x11+x07),18);
+
+ x01 ^= R((x00+x03), 7);
+ x02 ^= R((x01+x00), 9);
+ x03 ^= R((x02+x01),13);
+ x00 ^= R((x03+x02),18);
+ x06 ^= R((x05+x04), 7);
+ x07 ^= R((x06+x05), 9);
+ x04 ^= R((x07+x06),13);
+ x05 ^= R((x04+x07),18);
+ x11 ^= R((x10+x09), 7);
+ x08 ^= R((x11+x10), 9);
+ x09 ^= R((x08+x11),13);
+ x10 ^= R((x09+x08),18);
+ x12 ^= R((x15+x14), 7);
+ x13 ^= R((x12+x15), 9);
+ x14 ^= R((x13+x12),13);
+ x15 ^= R((x14+x13),18);
}
- for (int i = 0; i < StateSize; ++i)
- {
- x[i] += state[i];
- }
+ x[ 0] = x00 + input[ 0];
+ x[ 1] = x01 + input[ 1];
+ x[ 2] = x02 + input[ 2];
+ x[ 3] = x03 + input[ 3];
+ x[ 4] = x04 + input[ 4];
+ x[ 5] = x05 + input[ 5];
+ x[ 6] = x06 + input[ 6];
+ x[ 7] = x07 + input[ 7];
+ x[ 8] = x08 + input[ 8];
+ x[ 9] = x09 + input[ 9];
+ x[10] = x10 + input[10];
+ x[11] = x11 + input[11];
+ x[12] = x12 + input[12];
+ x[13] = x13 + input[13];
+ x[14] = x14 + input[14];
+ x[15] = x15 + input[15];
}
- private static uint R(uint x, int y)
+ /**
+ * Rotate left
+ *
+ * @param x value to rotate
+ * @param y amount to rotate x
+ *
+ * @return rotated x
+ */
+ internal static uint R(uint x, int y)
{
return (x << y) | (x >> (32 - y));
}
- private void ResetCounter()
+ private void ResetLimitCounter()
{
cW0 = 0;
cW1 = 0;
diff --git a/crypto/src/crypto/engines/XSalsa20Engine.cs b/crypto/src/crypto/engines/XSalsa20Engine.cs
new file mode 100644
index 000000000..fc6630905
--- /dev/null
+++ b/crypto/src/crypto/engines/XSalsa20Engine.cs
@@ -0,0 +1,71 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+ /// <summary>
+ /// Implementation of Daniel J. Bernstein's XSalsa20 stream cipher - Salsa20 with an extended nonce.
+ /// </summary>
+ /// <remarks>
+ /// XSalsa20 requires a 256 bit key, and a 192 bit nonce.
+ /// </remarks>
+ public class XSalsa20Engine
+ : Salsa20Engine
+ {
+
+ public override string AlgorithmName
+ {
+ get { return "XSalsa20"; }
+ }
+
+ protected override int NonceSize
+ {
+ get { return 24; }
+ }
+
+ /// <summary>
+ /// XSalsa20 key generation: process 256 bit input key and 128 bits of the input nonce
+ /// using a core Salsa20 function without input addition to produce 256 bit working key
+ /// and use that with the remaining 64 bits of nonce to initialize a standard Salsa20 engine state.
+ /// </summary>
+ protected override void SetKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ if (keyBytes.Length != 32)
+ {
+ throw new ArgumentException(AlgorithmName + " requires a 256 bit key");
+ }
+
+ // Set key for HSalsa20
+ base.SetKey(keyBytes, ivBytes);
+
+ // Pack next 64 bits of IV into engine state instead of counter
+ engineState[8] = Pack.LE_To_UInt32(ivBytes, 8);
+ engineState[9] = Pack.LE_To_UInt32(ivBytes, 12);
+
+ // Process engine state to generate Salsa20 key
+ uint[] hsalsa20Out = new uint[engineState.Length];
+ SalsaCore(20, engineState, hsalsa20Out);
+
+ // Set new key, removing addition in last round of salsaCore
+ engineState[1] = hsalsa20Out[0] - engineState[0];
+ engineState[2] = hsalsa20Out[5] - engineState[5];
+ engineState[3] = hsalsa20Out[10] - engineState[10];
+ engineState[4] = hsalsa20Out[15] - engineState[15];
+
+ engineState[11] = hsalsa20Out[6] - engineState[6];
+ engineState[12] = hsalsa20Out[7] - engineState[7];
+ engineState[13] = hsalsa20Out[8] - engineState[8];
+ engineState[14] = hsalsa20Out[9] - engineState[9];
+
+ // Last 64 bits of input IV
+ engineState[6] = Pack.LE_To_UInt32(ivBytes, 16);
+ engineState[7] = Pack.LE_To_UInt32(ivBytes, 20);
+
+ // Counter reset
+ ResetCounter();
+ }
+
+ }
+}
+
diff --git a/crypto/src/crypto/generators/ECKeyPairGenerator.cs b/crypto/src/crypto/generators/ECKeyPairGenerator.cs
index 8f2b1c2b5..a936755e2 100644
--- a/crypto/src/crypto/generators/ECKeyPairGenerator.cs
+++ b/crypto/src/crypto/generators/ECKeyPairGenerator.cs
@@ -81,6 +81,11 @@ namespace Org.BouncyCastle.Crypto.Generators
}
this.random = parameters.Random;
+
+ if (this.random == null)
+ {
+ this.random = new SecureRandom();
+ }
}
/**
diff --git a/crypto/src/crypto/generators/Poly1305KeyGenerator.cs b/crypto/src/crypto/generators/Poly1305KeyGenerator.cs
new file mode 100644
index 000000000..5deb50f07
--- /dev/null
+++ b/crypto/src/crypto/generators/Poly1305KeyGenerator.cs
@@ -0,0 +1,123 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+ /// <summary>
+ /// Generates keys for the Poly1305 MAC.
+ /// </summary>
+ /// <remarks>
+ /// Poly1305 keys are 256 bit keys consisting of a 128 bit secret key used for the underlying block
+ /// cipher followed by a 128 bit {@code r} value used for the polynomial portion of the Mac. <br/>
+ /// The {@code r} value has a specific format with some bits required to be cleared, resulting in an
+ /// effective 106 bit key. <br/>
+ /// A separately generated 256 bit key can be modified to fit the Poly1305 key format by using the
+ /// {@link #clamp(byte[])} method to clear the required bits.
+ /// </remarks>
+ /// <seealso cref="Poly1305"/>
+ public class Poly1305KeyGenerator
+ : CipherKeyGenerator
+ {
+ private const byte R_MASK_LOW_2 = (byte)0xFC;
+ private const byte R_MASK_HIGH_4 = (byte)0x0F;
+
+ /// <summary>
+ /// Initialises the key generator.
+ /// </summary>
+ /// <remarks>
+ /// Poly1305 keys are always 256 bits, so the key length in the provided parameters is ignored.
+ /// </remarks>
+ protected override void engineInit(KeyGenerationParameters param)
+ {
+ // Poly1305 keys are always 256 bits
+ this.random = param.Random;
+ this.strength = 32;
+ }
+
+ /// <summary>
+ /// Generates a 256 bit key in the format required for Poly1305 - e.g.
+ /// <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
+ /// as per <see cref="Clamp(byte[])"/>.
+ /// </summary>
+ protected override byte[] engineGenerateKey()
+ {
+ byte[] key = base.engineGenerateKey();
+ Clamp(key);
+ return key;
+ }
+
+ /// <summary>
+ /// Modifies an existing 32 byte key value to comply with the requirements of the Poly1305 key by
+ /// clearing required bits in the <code>r</code> (second 16 bytes) portion of the key.<br/>
+ /// Specifically:
+ /// <ul>
+ /// <li>r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})</li>
+ /// <li>r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252})</li>
+ /// </ul>
+ /// </summary>
+ /// <param name="key">a 32 byte key value <code>k[0] ... k[15], r[0] ... r[15]</code></param>
+ public static void Clamp(byte[] key)
+ {
+ /*
+ * Key is k[0] ... k[15], r[0] ... r[15] as per poly1305_aes_clamp in ref impl.
+ */
+ if (key.Length != 32)
+ {
+ throw new ArgumentException("Poly1305 key must be 256 bits.");
+ }
+
+ /*
+ * r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})
+ */
+ key[19] &= R_MASK_HIGH_4;
+ key[23] &= R_MASK_HIGH_4;
+ key[27] &= R_MASK_HIGH_4;
+ key[31] &= R_MASK_HIGH_4;
+
+ /*
+ * r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252}).
+ */
+ key[20] &= R_MASK_LOW_2;
+ key[24] &= R_MASK_LOW_2;
+ key[28] &= R_MASK_LOW_2;
+ }
+
+ /// <summary>
+ /// Checks a 32 byte key for compliance with the Poly1305 key requirements, e.g.
+ /// <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
+ /// as per <see cref="Clamp(byte[])"/>.
+ /// </summary>
+ /// <param name="key">Key.</param>
+ /// <exception cref="System.ArgumentException">if the key is of the wrong length, or has invalid bits set
+ /// in the <code>r</code> portion of the key.</exception>
+ public static void CheckKey(byte[] key)
+ {
+ if (key.Length != 32)
+ {
+ throw new ArgumentException("Poly1305 key must be 256 bits.");
+ }
+
+ checkMask(key[19], R_MASK_HIGH_4);
+ checkMask(key[23], R_MASK_HIGH_4);
+ checkMask(key[27], R_MASK_HIGH_4);
+ checkMask(key[31], R_MASK_HIGH_4);
+
+ checkMask(key[20], R_MASK_LOW_2);
+ checkMask(key[24], R_MASK_LOW_2);
+ checkMask(key[28], R_MASK_LOW_2);
+ }
+
+ private static void checkMask(byte b, byte mask)
+ {
+ if ((b & (~mask)) != 0)
+ {
+ throw new ArgumentException("Invalid format for r portion of Poly1305 key.");
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/macs/CMac.cs b/crypto/src/crypto/macs/CMac.cs
index b55a05605..682c12bac 100644
--- a/crypto/src/crypto/macs/CMac.cs
+++ b/crypto/src/crypto/macs/CMac.cs
@@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Crypto.Macs
private static int ShiftLeft(byte[] block, byte[] output)
{
- int i = 16;
+ int i = block.Length;
uint bit = 0;
while (--i >= 0)
{
diff --git a/crypto/src/crypto/macs/GMac.cs b/crypto/src/crypto/macs/GMac.cs
new file mode 100644
index 000000000..eb340ddbc
--- /dev/null
+++ b/crypto/src/crypto/macs/GMac.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+ /// <summary>
+ /// The GMAC specialisation of Galois/Counter mode (GCM) detailed in NIST Special Publication
+ /// 800-38D.
+ /// </summary>
+ /// <remarks>
+ /// GMac is an invocation of the GCM mode where no data is encrypted (i.e. all input data to the Mac
+ /// is processed as additional authenticated data with the underlying GCM block cipher).
+ /// </remarks>
+ public class GMac
+ : IMac
+ {
+ private readonly GcmBlockCipher cipher;
+ private readonly int macSizeBits;
+
+ /// <summary>
+ /// Creates a GMAC based on the operation of a block cipher in GCM mode.
+ /// </summary>
+ /// <remarks>
+ /// This will produce an authentication code the length of the block size of the cipher.
+ /// </remarks>
+ /// <param name="cipher">the cipher to be used in GCM mode to generate the MAC.</param>
+ public GMac(GcmBlockCipher cipher)
+ : this(cipher, 128)
+ {
+ }
+
+ /// <summary>
+ /// Creates a GMAC based on the operation of a 128 bit block cipher in GCM mode.
+ /// </summary>
+ /// <remarks>
+ /// This will produce an authentication code the length of the block size of the cipher.
+ /// </remarks>
+ /// <param name="cipher">the cipher to be used in GCM mode to generate the MAC.</param>
+ /// <param name="macSizeBits">the mac size to generate, in bits. Must be a multiple of 8, between 96 and 128 (inclusive).</param>
+ public GMac(GcmBlockCipher cipher, int macSizeBits)
+ {
+ this.cipher = cipher;
+ this.macSizeBits = macSizeBits;
+ }
+
+ /// <summary>
+ /// Initialises the GMAC - requires a <see cref="Org.BouncyCastle.Crypto.Parameters.ParametersWithIV"/>
+ /// providing a <see cref="Org.BouncyCastle.Crypto.Parameters.KeyParameter"/> and a nonce.
+ /// </summary>
+ public void Init(ICipherParameters parameters)
+ {
+ if (parameters is ParametersWithIV)
+ {
+ ParametersWithIV param = (ParametersWithIV)parameters;
+
+ byte[] iv = param.GetIV();
+ KeyParameter keyParam = (KeyParameter)param.Parameters;
+
+ // GCM is always operated in encrypt mode to calculate MAC
+ cipher.Init(true, new AeadParameters(keyParam, macSizeBits, iv));
+ }
+ else
+ {
+ throw new ArgumentException("GMAC requires ParametersWithIV");
+ }
+ }
+
+ public string AlgorithmName
+ {
+ get { return cipher.GetUnderlyingCipher().AlgorithmName + "-GMAC"; }
+ }
+
+ public int GetMacSize()
+ {
+ return macSizeBits / 8;
+ }
+
+ public void Update(byte input)
+ {
+ cipher.ProcessAadByte(input);
+ }
+
+ public void BlockUpdate(byte[] input, int inOff, int len)
+ {
+ cipher.ProcessAadBytes(input, inOff, len);
+ }
+
+ public int DoFinal(byte[] output, int outOff)
+ {
+ try
+ {
+ return cipher.DoFinal(output, outOff);
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // Impossible in encrypt mode
+ throw new InvalidOperationException(e.ToString());
+ }
+ }
+
+ public void Reset()
+ {
+ cipher.Reset();
+ }
+ }
+}
diff --git a/crypto/src/crypto/macs/Poly1305.cs b/crypto/src/crypto/macs/Poly1305.cs
new file mode 100644
index 000000000..2d453b6ad
--- /dev/null
+++ b/crypto/src/crypto/macs/Poly1305.cs
@@ -0,0 +1,272 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+
+ /// <summary>
+ /// Poly1305 message authentication code, designed by D. J. Bernstein.
+ /// </summary>
+ /// <remarks>
+ /// Poly1305 computes a 128-bit (16 bytes) authenticator, using a 128 bit nonce and a 256 bit key
+ /// consisting of a 128 bit key applied to an underlying cipher, and a 128 bit key (with 106
+ /// effective key bits) used in the authenticator.
+ ///
+ /// The polynomial calculation in this implementation is adapted from the public domain <a
+ /// href="https://github.com/floodyberry/poly1305-donna">poly1305-donna-unrolled</a> C implementation
+ /// by Andrew M (@floodyberry).
+ /// </remarks>
+ /// <seealso cref="Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator"/>
+ public class Poly1305
+ : IMac
+ {
+ private const int BLOCK_SIZE = 16;
+
+ private readonly IBlockCipher cipher;
+
+ private readonly byte[] singleByte = new byte[1];
+
+ // Initialised state
+
+ /** Polynomial key */
+ private uint r0, r1, r2, r3, r4;
+
+ /** Precomputed 5 * r[1..4] */
+ private uint s1, s2, s3, s4;
+
+ /** Encrypted nonce */
+ private uint k0, k1, k2, k3;
+
+ // Accumulating state
+
+ /** Current block of buffered input */
+ private byte[] currentBlock = new byte[BLOCK_SIZE];
+
+ /** Current offset in input buffer */
+ private int currentBlockOffset = 0;
+
+ /** Polynomial accumulator */
+ private uint h0, h1, h2, h3, h4;
+
+ /**
+ * Constructs a Poly1305 MAC, using a 128 bit block cipher.
+ */
+ public Poly1305(IBlockCipher cipher)
+ {
+ if (cipher.GetBlockSize() != BLOCK_SIZE)
+ {
+ throw new ArgumentException("Poly1305 requires a 128 bit block cipher.");
+ }
+ this.cipher = cipher;
+ }
+
+ /// <summary>
+ /// Initialises the Poly1305 MAC.
+ /// </summary>
+ /// <param name="parameters">a {@link ParametersWithIV} containing a 128 bit nonce and a {@link KeyParameter} with
+ /// a 256 bit key complying to the {@link Poly1305KeyGenerator Poly1305 key format}.</param>
+ public void Init(ICipherParameters parameters)
+ {
+ byte[] nonce;
+ byte[] key;
+ if ((parameters is ParametersWithIV) && ((ParametersWithIV)parameters).Parameters is KeyParameter)
+ {
+ nonce = ((ParametersWithIV)parameters).GetIV();
+ key = ((KeyParameter)((ParametersWithIV)parameters).Parameters).GetKey();
+ }
+ else
+ {
+ throw new ArgumentException("Poly1305 requires a key and and IV.");
+ }
+
+ setKey(key, nonce);
+ Reset();
+ }
+
+ private void setKey(byte[] key, byte[] nonce)
+ {
+ if (nonce.Length != BLOCK_SIZE)
+ {
+ throw new ArgumentException("Poly1305 requires a 128 bit IV.");
+ }
+ Poly1305KeyGenerator.CheckKey(key);
+
+ // Extract r portion of key
+ uint t0 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 0);
+ uint t1 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 4);
+ uint t2 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 8);
+ uint t3 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 12);
+
+ r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
+ r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
+ r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
+ r3 = t2 & 0x3f03fff; t3 >>= 8;
+ r4 = t3 & 0x00fffff;
+
+ // Precompute multipliers
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ // Compute encrypted nonce
+ byte[] cipherKey = new byte[BLOCK_SIZE];
+ Array.Copy(key, 0, cipherKey, 0, cipherKey.Length);
+
+ cipher.Init(true, new KeyParameter(cipherKey));
+ cipher.ProcessBlock(nonce, 0, cipherKey, 0);
+
+ k0 = Pack.LE_To_UInt32(cipherKey, 0);
+ k1 = Pack.LE_To_UInt32(cipherKey, 4);
+ k2 = Pack.LE_To_UInt32(cipherKey, 8);
+ k3 = Pack.LE_To_UInt32(cipherKey, 12);
+ }
+
+ public string AlgorithmName
+ {
+ get { return "Poly1305-" + cipher.AlgorithmName; }
+ }
+
+ public int GetMacSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public void Update(byte input)
+ {
+ singleByte[0] = input;
+ BlockUpdate(singleByte, 0, 1);
+ }
+
+ public void BlockUpdate(byte[] input, int inOff, int len)
+ {
+ int copied = 0;
+ while (len > copied)
+ {
+ if (currentBlockOffset == BLOCK_SIZE)
+ {
+ processBlock();
+ currentBlockOffset = 0;
+ }
+
+ int toCopy = System.Math.Min((len - copied), BLOCK_SIZE - currentBlockOffset);
+ Array.Copy(input, copied + inOff, currentBlock, currentBlockOffset, toCopy);
+ copied += toCopy;
+ currentBlockOffset += toCopy;
+ }
+
+ }
+
+ private void processBlock()
+ {
+ if (currentBlockOffset < BLOCK_SIZE)
+ {
+ currentBlock[currentBlockOffset] = 1;
+ for (int i = currentBlockOffset + 1; i < BLOCK_SIZE; i++)
+ {
+ currentBlock[i] = 0;
+ }
+ }
+
+ ulong t0 = Pack.LE_To_UInt32(currentBlock, 0);
+ ulong t1 = Pack.LE_To_UInt32(currentBlock, 4);
+ ulong t2 = Pack.LE_To_UInt32(currentBlock, 8);
+ ulong t3 = Pack.LE_To_UInt32(currentBlock, 12);
+
+ h0 += (uint)(t0 & 0x3ffffffU);
+ h1 += (uint)((((t1 << 32) | t0) >> 26) & 0x3ffffff);
+ h2 += (uint)((((t2 << 32) | t1) >> 20) & 0x3ffffff);
+ h3 += (uint)((((t3 << 32) | t2) >> 14) & 0x3ffffff);
+ h4 += (uint)(t3 >> 8);
+
+ if (currentBlockOffset == BLOCK_SIZE)
+ {
+ h4 += (1 << 24);
+ }
+
+ ulong tp0 = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1);
+ ulong tp1 = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2);
+ ulong tp2 = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3);
+ ulong tp3 = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4);
+ ulong tp4 = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0);
+
+ ulong b;
+ h0 = (uint)tp0 & 0x3ffffff; b = (tp0 >> 26);
+ tp1 += b; h1 = (uint)tp1 & 0x3ffffff; b = (tp1 >> 26);
+ tp2 += b; h2 = (uint)tp2 & 0x3ffffff; b = (tp2 >> 26);
+ tp3 += b; h3 = (uint)tp3 & 0x3ffffff; b = (tp3 >> 26);
+ tp4 += b; h4 = (uint)tp4 & 0x3ffffff; b = (tp4 >> 26);
+ h0 += (uint)(b * 5);
+ }
+
+ public int DoFinal(byte[] output, int outOff)
+ {
+ if (outOff + BLOCK_SIZE > output.Length)
+ {
+ throw new DataLengthException("Output buffer is too short.");
+ }
+
+ if (currentBlockOffset > 0)
+ {
+ // Process padded block
+ processBlock();
+ }
+
+ ulong f0, f1, f2, f3;
+
+ uint b = h0 >> 26;
+ h0 = h0 & 0x3ffffff;
+ h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff;
+ h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff;
+ h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff;
+ h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff;
+ h0 += b * 5;
+
+ uint g0, g1, g2, g3, g4;
+ g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
+ g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
+ g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
+ g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
+ g4 = h4 + b - (1 << 26);
+
+ b = (g4 >> 31) - 1;
+ uint nb = ~b;
+ h0 = (h0 & nb) | (g0 & b);
+ h1 = (h1 & nb) | (g1 & b);
+ h2 = (h2 & nb) | (g2 & b);
+ h3 = (h3 & nb) | (g3 & b);
+ h4 = (h4 & nb) | (g4 & b);
+
+ f0 = ((h0 ) | (h1 << 26)) + (ulong)k0;
+ f1 = ((h1 >> 6 ) | (h2 << 20)) + (ulong)k1;
+ f2 = ((h2 >> 12) | (h3 << 14)) + (ulong)k2;
+ f3 = ((h3 >> 18) | (h4 << 8 )) + (ulong)k3;
+
+ Pack.UInt32_To_LE((uint)f0, output, outOff);
+ f1 += (f0 >> 32);
+ Pack.UInt32_To_LE((uint)f1, output, outOff + 4);
+ f2 += (f1 >> 32);
+ Pack.UInt32_To_LE((uint)f2, output, outOff + 8);
+ f3 += (f2 >> 32);
+ Pack.UInt32_To_LE((uint)f3, output, outOff + 12);
+
+ Reset();
+ return BLOCK_SIZE;
+ }
+
+ public void Reset()
+ {
+ currentBlockOffset = 0;
+
+ h0 = h1 = h2 = h3 = h4 = 0;
+ }
+
+ private static ulong mul32x32_64(uint i1, uint i2)
+ {
+ return ((ulong)i1) * i2;
+ }
+ }
+}
diff --git a/crypto/src/crypto/modes/EAXBlockCipher.cs b/crypto/src/crypto/modes/EAXBlockCipher.cs
index bb027b597..5ccc69b66 100644
--- a/crypto/src/crypto/modes/EAXBlockCipher.cs
+++ b/crypto/src/crypto/modes/EAXBlockCipher.cs
@@ -65,6 +65,11 @@ namespace Org.BouncyCastle.Crypto.Modes
get { return cipher.GetUnderlyingCipher().AlgorithmName + "/EAX"; }
}
+ public IBlockCipher GetUnderlyingCipher()
+ {
+ return cipher;
+ }
+
public virtual int GetBlockSize()
{
return cipher.GetBlockSize();
diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs
index 95fe6f7ec..74b895e7b 100644
--- a/crypto/src/crypto/modes/GCMBlockCipher.cs
+++ b/crypto/src/crypto/modes/GCMBlockCipher.cs
@@ -69,6 +69,11 @@ namespace Org.BouncyCastle.Crypto.Modes
get { return cipher.AlgorithmName + "/GCM"; }
}
+ public IBlockCipher GetUnderlyingCipher()
+ {
+ return cipher;
+ }
+
public virtual int GetBlockSize()
{
return BlockSize;
diff --git a/crypto/src/crypto/modes/IAeadBlockCipher.cs b/crypto/src/crypto/modes/IAeadBlockCipher.cs
index 06bc50488..52c4ff428 100644
--- a/crypto/src/crypto/modes/IAeadBlockCipher.cs
+++ b/crypto/src/crypto/modes/IAeadBlockCipher.cs
@@ -11,6 +11,9 @@ namespace Org.BouncyCastle.Crypto.Modes
/// <summary>The name of the algorithm this cipher implements.</summary>
string AlgorithmName { get; }
+ /// <summary>The block cipher underlying this algorithm.</summary>
+ IBlockCipher GetUnderlyingCipher();
+
/// <summary>Initialise the cipher.</summary>
/// <remarks>Parameter can either be an AeadParameters or a ParametersWithIV object.</remarks>
/// <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
diff --git a/crypto/src/crypto/tls/AlertDescription.cs b/crypto/src/crypto/tls/AlertDescription.cs
index e1229a4a3..e09da6cab 100644
--- a/crypto/src/crypto/tls/AlertDescription.cs
+++ b/crypto/src/crypto/tls/AlertDescription.cs
@@ -1,47 +1,217 @@
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 2246 7.2
- /// </summary>
- public enum AlertDescription : byte
- {
- close_notify = 0,
- unexpected_message = 10,
- bad_record_mac = 20,
- decryption_failed = 21,
- record_overflow = 22,
- decompression_failure = 30,
- handshake_failure = 40,
- /* 41 is not defined, for historical reasons */
- bad_certificate = 42,
- unsupported_certificate = 43,
- certificate_revoked = 44,
- certificate_expired = 45,
- certificate_unknown = 46,
- illegal_parameter = 47,
- unknown_ca = 48,
- access_denied = 49,
- decode_error = 50,
- decrypt_error = 51,
- export_restriction = 60,
- protocol_version = 70,
- insufficient_security = 71,
- internal_error = 80,
- user_canceled = 90,
- no_renegotiation = 100,
-
- /*
- * RFC 3546
- */
- unsupported_extension = 110,
- certificate_unobtainable = 111,
- unrecognized_name = 112,
- bad_certificate_status_response = 113,
- bad_certificate_hash_value = 114,
-
- /*
- * RFC 4279
- */
- unknown_psk_identity = 115,
- }
+ /// <summary>
+ /// RFC 5246 7.2
+ /// </summary>
+ public abstract class AlertDescription
+ {
+ /**
+ * This message notifies the recipient that the sender will not send any more messages on this
+ * connection. Note that as of TLS 1.1, failure to properly close a connection no longer
+ * requires that a session not be resumed. This is a change from TLS 1.0 ("The session becomes
+ * unresumable if any connection is terminated without proper close_notify messages with level
+ * equal to warning.") to conform with widespread implementation practice.
+ */
+ public const byte close_notify = 0;
+
+ /**
+ * An inappropriate message was received. This alert is always fatal and should never be
+ * observed in communication between proper implementations.
+ */
+ public const byte unexpected_message = 10;
+
+ /**
+ * This alert is returned if a record is received with an incorrect MAC. This alert also MUST be
+ * returned if an alert is sent because a TLSCiphertext decrypted in an invalid way: either it
+ * wasn't an even multiple of the block length, or its padding values, when checked, weren't
+ * correct. This message is always fatal and should never be observed in communication between
+ * proper implementations (except when messages were corrupted in the network).
+ */
+ public const byte bad_record_mac = 20;
+
+ /**
+ * This alert was used in some earlier versions of TLS, and may have permitted certain attacks
+ * against the CBC mode [CBCATT]. It MUST NOT be sent by compliant implementations.
+ */
+ public const byte decryption_failed = 21;
+
+ /**
+ * A TLSCiphertext record was received that had a length more than 2^14+2048 bytes, or a record
+ * decrypted to a TLSCompressed record with more than 2^14+1024 bytes. This message is always
+ * fatal and should never be observed in communication between proper implementations (except
+ * when messages were corrupted in the network).
+ */
+ public const byte record_overflow = 22;
+
+ /**
+ * The decompression function received improper input (e.g., data that would expand to excessive
+ * length). This message is always fatal and should never be observed in communication between
+ * proper implementations.
+ */
+ public const byte decompression_failure = 30;
+
+ /**
+ * Reception of a handshake_failure alert message indicates that the sender was unable to
+ * negotiate an acceptable set of security parameters given the options available. This is a
+ * fatal error.
+ */
+ public const byte handshake_failure = 40;
+
+ /**
+ * This alert was used in SSLv3 but not any version of TLS. It MUST NOT be sent by compliant
+ * implementations.
+ */
+ public const byte no_certificate = 41;
+
+ /**
+ * A certificate was corrupt, contained signatures that did not verify correctly, etc.
+ */
+ public const byte bad_certificate = 42;
+
+ /**
+ * A certificate was of an unsupported type.
+ */
+ public const byte unsupported_certificate = 43;
+
+ /**
+ * A certificate was revoked by its signer.
+ */
+ public const byte certificate_revoked = 44;
+
+ /**
+ * A certificate has expired or is not currently valid.
+ */
+ public const byte certificate_expired = 45;
+
+ /**
+ * Some other (unspecified) issue arose in processing the certificate, rendering it
+ * unacceptable.
+ */
+ public const byte certificate_unknown = 46;
+
+ /**
+ * A field in the handshake was out of range or inconsistent with other fields. This message is
+ * always fatal.
+ */
+ public const byte illegal_parameter = 47;
+
+ /**
+ * A valid certificate chain or partial chain was received, but the certificate was not accepted
+ * because the CA certificate could not be located or couldn't be matched with a known, trusted
+ * CA. This message is always fatal.
+ */
+ public const byte unknown_ca = 48;
+
+ /**
+ * A valid certificate was received, but when access control was applied, the sender decided not
+ * to proceed with negotiation. This message is always fatal.
+ */
+ public const byte access_denied = 49;
+
+ /**
+ * A message could not be decoded because some field was out of the specified range or the
+ * length of the message was incorrect. This message is always fatal and should never be
+ * observed in communication between proper implementations (except when messages were corrupted
+ * in the network).
+ */
+ public const byte decode_error = 50;
+
+ /**
+ * A handshake cryptographic operation failed, including being unable to correctly verify a
+ * signature or validate a Finished message. This message is always fatal.
+ */
+ public const byte decrypt_error = 51;
+
+ /**
+ * This alert was used in some earlier versions of TLS. It MUST NOT be sent by compliant
+ * implementations.
+ */
+ public const byte export_restriction = 60;
+
+ /**
+ * The protocol version the client has attempted to negotiate is recognized but not supported.
+ * (For example, old protocol versions might be avoided for security reasons.) This message is
+ * always fatal.
+ */
+ public const byte protocol_version = 70;
+
+ /**
+ * Returned instead of handshake_failure when a negotiation has failed specifically because the
+ * server requires ciphers more secure than those supported by the client. This message is
+ * always fatal.
+ */
+ public const byte insufficient_security = 71;
+
+ /**
+ * An internal error unrelated to the peer or the correctness of the protocol (such as a memory
+ * allocation failure) makes it impossible to continue. This message is always fatal.
+ */
+ public const byte internal_error = 80;
+
+ /**
+ * This handshake is being canceled for some reason unrelated to a protocol failure. If the user
+ * cancels an operation after the handshake is complete, just closing the connection by sending
+ * a close_notify is more appropriate. This alert should be followed by a close_notify. This
+ * message is generally a warning.
+ */
+ public const byte user_canceled = 90;
+
+ /**
+ * Sent by the client in response to a hello request or by the server in response to a client
+ * hello after initial handshaking. Either of these would normally lead to renegotiation; when
+ * that is not appropriate, the recipient should respond with this alert. At that point, the
+ * original requester can decide whether to proceed with the connection. One case where this
+ * would be appropriate is where a server has spawned a process to satisfy a request; the
+ * process might receive security parameters (key length, authentication, etc.) at startup, and
+ * it might be difficult to communicate changes to these parameters after that point. This
+ * message is always a warning.
+ */
+ public const byte no_renegotiation = 100;
+
+ /**
+ * Sent by clients that receive an extended server hello containing an extension that they did
+ * not put in the corresponding client hello. This message is always fatal.
+ */
+ public const byte unsupported_extension = 110;
+
+ /*
+ * RFC 3546
+ */
+
+ /**
+ * This alert is sent by servers who are unable to retrieve a certificate chain from the URL
+ * supplied by the client (see Section 3.3). This message MAY be fatal - for example if client
+ * authentication is required by the server for the handshake to continue and the server is
+ * unable to retrieve the certificate chain, it may send a fatal alert.
+ */
+ public const byte certificate_unobtainable = 111;
+
+ /**
+ * This alert is sent by servers that receive a server_name extension request, but do not
+ * recognize the server name. This message MAY be fatal.
+ */
+ public const byte unrecognized_name = 112;
+
+ /**
+ * This alert is sent by clients that receive an invalid certificate status response (see
+ * Section 3.6). This message is always fatal.
+ */
+ public const byte bad_certificate_status_response = 113;
+
+ /**
+ * This alert is sent by servers when a certificate hash does not match a client provided
+ * certificate_hash. This message is always fatal.
+ */
+ public const byte bad_certificate_hash_value = 114;
+
+ /*
+ * RFC 4279
+ */
+
+ /**
+ * If the server does not recognize the PSK identity, it MAY respond with an
+ * "unknown_psk_identity" alert message.
+ */
+ public const byte unknown_psk_identity = 115;
+ }
}
diff --git a/crypto/src/crypto/tls/AlertLevel.cs b/crypto/src/crypto/tls/AlertLevel.cs
index afb04308b..d77251dfb 100644
--- a/crypto/src/crypto/tls/AlertLevel.cs
+++ b/crypto/src/crypto/tls/AlertLevel.cs
@@ -1,11 +1,11 @@
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 2246 7.2
- /// </summary>
- public enum AlertLevel : byte
- {
- warning = 1,
- fatal = 2,
- }
+ /// <summary>
+ /// RFC 5246 7.2
+ /// </summary>
+ public abstract class AlertLevel
+ {
+ public const byte warning = 1;
+ public const byte fatal = 2;
+ }
}
diff --git a/crypto/src/crypto/tls/ByteQueue.cs b/crypto/src/crypto/tls/ByteQueue.cs
index c3ce91402..f9398bbaf 100644
--- a/crypto/src/crypto/tls/ByteQueue.cs
+++ b/crypto/src/crypto/tls/ByteQueue.cs
@@ -68,13 +68,13 @@ namespace Org.BouncyCastle.Crypto.Tls
int len,
int skip)
{
- if ((available - skip) < len)
+ if ((buf.Length - offset) < len)
{
- throw new TlsException("Not enough data to read");
+ throw new ArgumentException("Buffer size of " + buf.Length + " is too small for a read of " + len + " bytes");
}
- if ((buf.Length - offset) < len)
+ if ((available - skip) < len)
{
- throw new TlsException("Buffer size of " + buf.Length + " is too small for a read of " + len + " bytes");
+ throw new InvalidOperationException("Not enough data to read");
}
Array.Copy(databuf, skipped + skip, buf, offset, len);
}
@@ -115,7 +115,7 @@ namespace Org.BouncyCastle.Crypto.Tls
{
if (i > available)
{
- throw new TlsException("Cannot remove " + i + " bytes, only got " + available);
+ throw new InvalidOperationException("Cannot remove " + i + " bytes, only got " + available);
}
/*
diff --git a/crypto/src/crypto/tls/Certificate.cs b/crypto/src/crypto/tls/Certificate.cs
index e4df041e2..12bfa9214 100644
--- a/crypto/src/crypto/tls/Certificate.cs
+++ b/crypto/src/crypto/tls/Certificate.cs
@@ -8,104 +8,136 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls
{
- /**
- * A representation for a certificate chain.
- */
- public class Certificate
- {
- public static readonly Certificate EmptyChain = new Certificate(new X509CertificateStructure[0]);
-
- /**
- * The certificates.
- */
- internal X509CertificateStructure[] certs;
-
- /**
- * Parse the ServerCertificate message.
- *
- * @param inStr The stream where to parse from.
- * @return A Certificate object with the certs, the server has sended.
- * @throws IOException If something goes wrong during parsing.
- */
- internal static Certificate Parse(
- Stream inStr)
- {
- int left = TlsUtilities.ReadUint24(inStr);
- if (left == 0)
- {
- return EmptyChain;
- }
- IList tmp = Platform.CreateArrayList();
- while (left > 0)
- {
- int size = TlsUtilities.ReadUint24(inStr);
- left -= 3 + size;
- byte[] buf = new byte[size];
- TlsUtilities.ReadFully(buf, inStr);
- MemoryStream bis = new MemoryStream(buf, false);
- Asn1Object o = Asn1Object.FromStream(bis);
- tmp.Add(X509CertificateStructure.GetInstance(o));
- if (bis.Position < bis.Length)
- {
- throw new ArgumentException("Sorry, there is garbage data left after the certificate");
- }
- }
- X509CertificateStructure[] certs = new X509CertificateStructure[tmp.Count];
- for (int i = 0; i < tmp.Count; ++i)
+ /**
+ * Parsing and encoding of a <i>Certificate</i> struct from RFC 4346.
+ * <p/>
+ * <pre>
+ * opaque ASN.1Cert<2^24-1>;
+ *
+ * struct {
+ * ASN.1Cert certificate_list<0..2^24-1>;
+ * } Certificate;
+ * </pre>
+ *
+ * @see Org.BouncyCastle.Asn1.X509.X509CertificateStructure
+ */
+ public class Certificate
+ {
+ public static readonly Certificate EmptyChain = new Certificate(new X509CertificateStructure[0]);
+
+ /**
+ * The certificates.
+ */
+ protected readonly X509CertificateStructure[] mCertificateList;
+
+ public Certificate(X509CertificateStructure[] certificateList)
+ {
+ if (certificateList == null)
+ throw new ArgumentNullException("certificateList");
+
+ this.mCertificateList = certificateList;
+ }
+
+ /// <returns>An array which contains the certs, this chain contains.</returns>
+ [Obsolete("Use 'GetCertificateList' instead")]
+ public virtual X509CertificateStructure[] GetCerts()
+ {
+ return GetCertificateList();
+ }
+
+ /**
+ * @return an array of {@link org.bouncycastle.asn1.x509.Certificate} representing a certificate
+ * chain.
+ */
+ public virtual X509CertificateStructure[] GetCertificateList()
+ {
+ return CloneCertificateList();
+ }
+
+ public virtual X509CertificateStructure GetCertificateAt(int index)
+ {
+ return mCertificateList[index];
+ }
+
+ public virtual int Length
+ {
+ get { return mCertificateList.Length; }
+ }
+
+ /**
+ * @return <code>true</code> if this certificate chain contains no certificates, or
+ * <code>false</code> otherwise.
+ */
+ public virtual bool IsEmpty
+ {
+ get { return mCertificateList.Length == 0; }
+ }
+
+ /**
+ * Encode this {@link Certificate} to a {@link Stream}.
+ *
+ * @param output the {@link Stream} to encode to.
+ * @throws IOException
+ */
+ public virtual void Encode(Stream output)
+ {
+ IList derEncodings = Platform.CreateArrayList(mCertificateList.Length);
+
+ int totalLength = 0;
+ foreach (Asn1Encodable asn1Cert in mCertificateList)
+ {
+ byte[] derEncoding = asn1Cert.GetEncoded(Asn1Encodable.Der);
+ derEncodings.Add(derEncoding);
+ totalLength += derEncoding.Length + 3;
+ }
+
+ TlsUtilities.CheckUint24(totalLength);
+ TlsUtilities.WriteUint24(totalLength, output);
+
+ foreach (byte[] derEncoding in derEncodings)
+ {
+ TlsUtilities.WriteOpaque24(derEncoding, output);
+ }
+ }
+
+ /**
+ * Parse a {@link Certificate} from a {@link Stream}.
+ *
+ * @param input the {@link Stream} to parse from.
+ * @return a {@link Certificate} object.
+ * @throws IOException
+ */
+ public static Certificate Parse(Stream input)
+ {
+ int totalLength = TlsUtilities.ReadUint24(input);
+ if (totalLength == 0)
{
- certs[i] = (X509CertificateStructure)tmp[i];
+ return EmptyChain;
}
- return new Certificate(certs);
- }
-
- /**
- * Encodes version of the ClientCertificate message
- *
- * @param outStr stream to write the message to
- * @throws IOException If something goes wrong
- */
- internal void Encode(
- Stream outStr)
- {
- IList encCerts = Platform.CreateArrayList();
- int totalSize = 0;
- foreach (X509CertificateStructure cert in certs)
- {
- byte[] encCert = cert.GetEncoded(Asn1Encodable.Der);
- encCerts.Add(encCert);
- totalSize += encCert.Length + 3;
- }
-
- TlsUtilities.WriteUint24(totalSize, outStr);
-
- foreach (byte[] encCert in encCerts)
- {
- TlsUtilities.WriteOpaque24(encCert, outStr);
- }
- }
-
- /**
- * Private constructor from a cert array.
- *
- * @param certs The certs the chain should contain.
- */
- public Certificate(X509CertificateStructure[] certs)
- {
- if (certs == null)
- throw new ArgumentNullException("certs");
-
- this.certs = certs;
- }
-
- /// <returns>An array which contains the certs, this chain contains.</returns>
- public X509CertificateStructure[] GetCerts()
- {
- return (X509CertificateStructure[]) certs.Clone();
- }
-
- public bool IsEmpty
- {
- get { return certs.Length == 0; }
- }
- }
+
+ byte[] certListData = TlsUtilities.ReadFully(totalLength, input);
+
+ MemoryStream buf = new MemoryStream(certListData, false);
+
+ IList certificate_list = Platform.CreateArrayList();
+ while (buf.Position < buf.Length)
+ {
+ byte[] derEncoding = TlsUtilities.ReadOpaque24(buf);
+ Asn1Object asn1Cert = TlsUtilities.ReadDerObject(derEncoding);
+ certificate_list.Add(X509CertificateStructure.GetInstance(asn1Cert));
+ }
+
+ X509CertificateStructure[] certificateList = new X509CertificateStructure[certificate_list.Count];
+ for (int i = 0; i < certificate_list.Count; ++i)
+ {
+ certificateList[i] = (X509CertificateStructure)certificate_list[i];
+ }
+ return new Certificate(certificateList);
+ }
+
+ protected virtual X509CertificateStructure[] CloneCertificateList()
+ {
+ return (X509CertificateStructure[])mCertificateList.Clone();
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/CertificateRequest.cs b/crypto/src/crypto/tls/CertificateRequest.cs
index 49d8ba6fb..8ab265513 100644
--- a/crypto/src/crypto/tls/CertificateRequest.cs
+++ b/crypto/src/crypto/tls/CertificateRequest.cs
@@ -1,28 +1,158 @@
using System;
using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls
{
- public class CertificateRequest
- {
- private ClientCertificateType[] certificateTypes;
- private IList certificateAuthorities;
-
- public CertificateRequest(ClientCertificateType[] certificateTypes, IList certificateAuthorities)
- {
- this.certificateTypes = certificateTypes;
- this.certificateAuthorities = certificateAuthorities;
- }
-
- public ClientCertificateType[] CertificateTypes
- {
- get { return certificateTypes; }
- }
-
- /// <returns>A <see cref="IList"/> of X509Name</returns>
- public IList CertificateAuthorities
- {
- get { return certificateAuthorities; }
- }
- }
-}
\ No newline at end of file
+ /**
+ * Parsing and encoding of a <i>CertificateRequest</i> struct from RFC 4346.
+ * <p/>
+ * <pre>
+ * struct {
+ * ClientCertificateType certificate_types<1..2^8-1>;
+ * DistinguishedName certificate_authorities<3..2^16-1>
+ * } CertificateRequest;
+ * </pre>
+ *
+ * @see ClientCertificateType
+ * @see X509Name
+ */
+ public class CertificateRequest
+ {
+ protected readonly byte[] mCertificateTypes;
+ protected readonly IList mSupportedSignatureAlgorithms;
+ protected readonly IList mCertificateAuthorities;
+
+ /**
+ * @param certificateTypes see {@link ClientCertificateType} for valid constants.
+ * @param certificateAuthorities an {@link IList} of {@link X509Name}.
+ */
+ public CertificateRequest(byte[] certificateTypes, IList supportedSignatureAlgorithms,
+ IList certificateAuthorities)
+ {
+ this.mCertificateTypes = certificateTypes;
+ this.mSupportedSignatureAlgorithms = supportedSignatureAlgorithms;
+ this.mCertificateAuthorities = certificateAuthorities;
+ }
+
+ /**
+ * @return an array of certificate types
+ * @see {@link ClientCertificateType}
+ */
+ public virtual byte[] CertificateTypes
+ {
+ get { return mCertificateTypes; }
+ }
+
+ /**
+ * @return an {@link IList} of {@link SignatureAndHashAlgorithm} (or null before TLS 1.2).
+ */
+ public virtual IList SupportedSignatureAlgorithms
+ {
+ get { return mSupportedSignatureAlgorithms; }
+ }
+
+ /**
+ * @return an {@link IList} of {@link X509Name}
+ */
+ public virtual IList CertificateAuthorities
+ {
+ get { return mCertificateAuthorities; }
+ }
+
+ /**
+ * Encode this {@link CertificateRequest} to a {@link Stream}.
+ *
+ * @param output the {@link Stream} to encode to.
+ * @throws IOException
+ */
+ public virtual void Encode(Stream output)
+ {
+ if (mCertificateTypes == null || mCertificateTypes.Length == 0)
+ {
+ TlsUtilities.WriteUint8(0, output);
+ }
+ else
+ {
+ TlsUtilities.WriteUint8ArrayWithUint8Length(mCertificateTypes, output);
+ }
+
+ if (mSupportedSignatureAlgorithms != null)
+ {
+ // TODO Check whether SignatureAlgorithm.anonymous is allowed here
+ TlsUtilities.EncodeSupportedSignatureAlgorithms(mSupportedSignatureAlgorithms, false, output);
+ }
+
+ if (mCertificateAuthorities == null || mCertificateAuthorities.Count < 1)
+ {
+ TlsUtilities.WriteUint16(0, output);
+ }
+ else
+ {
+ IList derEncodings = Platform.CreateArrayList(mCertificateAuthorities.Count);
+
+ int totalLength = 0;
+ foreach (Asn1Encodable certificateAuthority in mCertificateAuthorities)
+ {
+ byte[] derEncoding = certificateAuthority.GetEncoded(Asn1Encodable.Der);
+ derEncodings.Add(derEncoding);
+ totalLength += derEncoding.Length;
+ }
+
+ TlsUtilities.CheckUint16(totalLength);
+ TlsUtilities.WriteUint16(totalLength, output);
+
+ foreach (byte[] derEncoding in derEncodings)
+ {
+ output.Write(derEncoding, 0, derEncoding.Length);
+ }
+ }
+ }
+
+ /**
+ * Parse a {@link CertificateRequest} from a {@link Stream}.
+ *
+ * @param context
+ * the {@link TlsContext} of the current connection.
+ * @param input
+ * the {@link Stream} to parse from.
+ * @return a {@link CertificateRequest} object.
+ * @throws IOException
+ */
+ public static CertificateRequest Parse(//TlsContext context,
+ Stream input)
+ {
+ int numTypes = TlsUtilities.ReadUint8(input);
+ byte[] certificateTypes = new byte[numTypes];
+ for (int i = 0; i < numTypes; ++i)
+ {
+ certificateTypes[i] = TlsUtilities.ReadUint8(input);
+ }
+
+ // TODO Add TLS 1.2 support here
+ IList supportedSignatureAlgorithms = null;
+ //if (TlsUtilities.IsTLSv12(context))
+ //{
+ // // TODO Check whether SignatureAlgorithm.anonymous is allowed here
+ // supportedSignatureAlgorithms = TlsUtilities.ParseSupportedSignatureAlgorithms(false, input);
+ //}
+
+ IList certificateAuthorities = Platform.CreateArrayList();
+ byte[] certAuthData = TlsUtilities.ReadOpaque16(input);
+ MemoryStream bis = new MemoryStream(certAuthData, false);
+ while (bis.Position < bis.Length)
+ {
+ byte[] derEncoding = TlsUtilities.ReadOpaque16(bis);
+ Asn1Object asn1 = TlsUtilities.ReadDerObject(derEncoding);
+ // TODO Switch to X500Name when available
+ certificateAuthorities.Add(X509Name.GetInstance(asn1));
+ }
+
+ return new CertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities);
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/CipherSuite.cs b/crypto/src/crypto/tls/CipherSuite.cs
index 6e1f7a545..2c5077780 100644
--- a/crypto/src/crypto/tls/CipherSuite.cs
+++ b/crypto/src/crypto/tls/CipherSuite.cs
@@ -1,136 +1,298 @@
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 2246 A.5
- /// </summary>
- public enum CipherSuite : int
- {
- TLS_NULL_WITH_NULL_NULL = 0x0000,
- TLS_RSA_WITH_NULL_MD5 = 0x0001,
- TLS_RSA_WITH_NULL_SHA = 0x0002,
- TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003,
- TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
- TLS_RSA_WITH_RC4_128_SHA = 0x0005,
- TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006,
- TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007,
- TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008,
- TLS_RSA_WITH_DES_CBC_SHA = 0x0009,
- TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A,
- TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B,
- TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C,
- TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D,
- TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E,
- TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F,
- TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010,
- TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011,
- TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012,
- TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
- TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014,
- TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015,
- TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
- TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017,
- TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
- TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019,
- TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A,
- TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B,
-
- /*
- * RFC 3268
- */
- TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F,
- TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030,
- TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031,
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032,
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033,
- TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034,
- TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035,
- TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036,
- TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037,
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038,
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039,
- TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A,
-
- /*
- * RFC 4279
- */
- TLS_PSK_WITH_RC4_128_SHA = 0x008A,
- TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B,
- TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C,
- TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D,
- TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E,
- TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F,
- TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090,
- TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091,
- TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092,
- TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093,
- TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094,
- TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095,
-
- /*
- * RFC 4492
- */
- TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001,
- TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002,
- TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003,
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004,
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005,
- TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006,
- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007,
- TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008,
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009,
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A,
- TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B,
- TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C,
- TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D,
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E,
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F,
- TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010,
- TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011,
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012,
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013,
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014,
- TLS_ECDH_anon_WITH_NULL_SHA = 0xC015,
- TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016,
- TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017,
- TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018,
- TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019,
-
- /*
- * RFC 5054
- */
- TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A,
- TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B,
- TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C,
- TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D,
- TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E,
- TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F,
- TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020,
- TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021,
- TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022,
-
- /*
- * RFC 5289
- */
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024,
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025,
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026,
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028,
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029,
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A,
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B,
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C,
- TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D,
- TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E,
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F,
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030,
- TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031,
- TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032,
-
- /*
- * RFC 5746
- */
- TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
- }
+ /// <summary>
+ /// RFC 2246 A.5
+ /// </summary>
+ public abstract class CipherSuite
+ {
+ public const int TLS_NULL_WITH_NULL_NULL = 0x0000;
+ public const int TLS_RSA_WITH_NULL_MD5 = 0x0001;
+ public const int TLS_RSA_WITH_NULL_SHA = 0x0002;
+ public const int TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003;
+ public const int TLS_RSA_WITH_RC4_128_MD5 = 0x0004;
+ public const int TLS_RSA_WITH_RC4_128_SHA = 0x0005;
+ public const int TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006;
+ public const int TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007;
+ public const int TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008;
+ public const int TLS_RSA_WITH_DES_CBC_SHA = 0x0009;
+ public const int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A;
+ public const int TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B;
+ public const int TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C;
+ public const int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D;
+ public const int TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E;
+ public const int TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F;
+ public const int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010;
+ public const int TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011;
+ public const int TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012;
+ public const int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013;
+ public const int TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014;
+ public const int TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015;
+ public const int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
+ public const int TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017;
+ public const int TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018;
+ public const int TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019;
+ public const int TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A;
+ public const int TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B;
+
+ /*
+ * Note: The cipher suite values { 0x00, 0x1C } and { 0x00, 0x1D } are reserved to avoid
+ * collision with Fortezza-based cipher suites in SSL 3.
+ */
+
+ /*
+ * RFC 3268
+ */
+ public const int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F;
+ public const int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030;
+ public const int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031;
+ public const int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032;
+ public const int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
+ public const int TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034;
+ public const int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
+ public const int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036;
+ public const int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037;
+ public const int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038;
+ public const int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
+ public const int TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A;
+
+ /*
+ * RFC 4132
+ */
+ public const int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041;
+ public const int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042;
+ public const int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043;
+ public const int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044;
+ public const int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045;
+ public const int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046;
+ public const int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084;
+ public const int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085;
+ public const int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086;
+ public const int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087;
+ public const int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088;
+ public const int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089;
+
+ /*
+ * RFC 4162
+ */
+ public const int TLS_RSA_WITH_SEED_CBC_SHA = 0x0096;
+ public const int TLS_DH_DSS_WITH_SEED_CBC_SHA = 0x0097;
+ public const int TLS_DH_RSA_WITH_SEED_CBC_SHA = 0x0098;
+ public const int TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099;
+ public const int TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A;
+ public const int TLS_DH_anon_WITH_SEED_CBC_SHA = 0x009B;
+
+ /*
+ * RFC 4279
+ */
+ public const int TLS_PSK_WITH_RC4_128_SHA = 0x008A;
+ public const int TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B;
+ public const int TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C;
+ public const int TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D;
+ public const int TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E;
+ public const int TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F;
+ public const int TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090;
+ public const int TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091;
+ public const int TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092;
+ public const int TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093;
+ public const int TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094;
+ public const int TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095;
+
+ /*
+ * RFC 4492
+ */
+ public const int TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001;
+ public const int TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002;
+ public const int TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003;
+ public const int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004;
+ public const int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005;
+ public const int TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006;
+ public const int TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007;
+ public const int TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008;
+ public const int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009;
+ public const int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A;
+ public const int TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B;
+ public const int TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C;
+ public const int TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D;
+ public const int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E;
+ public const int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F;
+ public const int TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010;
+ public const int TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011;
+ public const int TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012;
+ public const int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013;
+ public const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014;
+ public const int TLS_ECDH_anon_WITH_NULL_SHA = 0xC015;
+ public const int TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016;
+ public const int TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017;
+ public const int TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018;
+ public const int TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019;
+
+ /*
+ * RFC 4785
+ */
+ public const int TLS_PSK_WITH_NULL_SHA = 0x002C;
+ public const int TLS_DHE_PSK_WITH_NULL_SHA = 0x002D;
+ public const int TLS_RSA_PSK_WITH_NULL_SHA = 0x002E;
+
+ /*
+ * RFC 5054
+ */
+ public const int TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A;
+ public const int TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B;
+ public const int TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C;
+ public const int TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D;
+ public const int TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E;
+ public const int TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F;
+ public const int TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020;
+ public const int TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021;
+ public const int TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022;
+
+ /*
+ * RFC 5246
+ */
+ public const int TLS_RSA_WITH_NULL_SHA256 = 0x003B;
+ public const int TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C;
+ public const int TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D;
+ public const int TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E;
+ public const int TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F;
+ public const int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040;
+ public const int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067;
+ public const int TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068;
+ public const int TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069;
+ public const int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A;
+ public const int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B;
+ public const int TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C;
+ public const int TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D;
+
+ /*
+ * RFC 5288
+ */
+ public const int TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C;
+ public const int TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D;
+ public const int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E;
+ public const int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F;
+ public const int TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0;
+ public const int TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1;
+ public const int TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2;
+ public const int TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3;
+ public const int TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4;
+ public const int TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5;
+ public const int TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6;
+ public const int TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7;
+
+ /*
+ * RFC 5289
+ */
+ public const int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023;
+ public const int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024;
+ public const int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025;
+ public const int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026;
+ public const int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027;
+ public const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028;
+ public const int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029;
+ public const int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A;
+ public const int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B;
+ public const int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C;
+ public const int TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D;
+ public const int TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E;
+ public const int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F;
+ public const int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030;
+ public const int TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031;
+ public const int TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032;
+
+ /*
+ * RFC 5487
+ */
+ public const int TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8;
+ public const int TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9;
+ public const int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA;
+ public const int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB;
+ public const int TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC;
+ public const int TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD;
+ public const int TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE;
+ public const int TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF;
+ public const int TLS_PSK_WITH_NULL_SHA256 = 0x00B0;
+ public const int TLS_PSK_WITH_NULL_SHA384 = 0x00B1;
+ public const int TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2;
+ public const int TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3;
+ public const int TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4;
+ public const int TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5;
+ public const int TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6;
+ public const int TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7;
+ public const int TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8;
+ public const int TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9;
+
+ /*
+ * RFC 5489
+ */
+ public const int TLS_ECDHE_PSK_WITH_RC4_128_SHA = 0xC033;
+ public const int TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 0xC034;
+ public const int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035;
+ public const int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036;
+ public const int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0xC037;
+ public const int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 0xC038;
+ public const int TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039;
+ public const int TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A;
+ public const int TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B;
+
+ /*
+ * RFC 5746
+ */
+ public const int TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
+
+ /*
+ * RFC 6655
+ */
+ public const int TLS_RSA_WITH_AES_128_CCM = 0xC09C;
+ public const int TLS_RSA_WITH_AES_256_CCM = 0xC09D;
+ public const int TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E;
+ public const int TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F;
+ public const int TLS_RSA_WITH_AES_128_CCM_8 = 0xC0A0;
+ public const int TLS_RSA_WITH_AES_256_CCM_8 = 0xC0A1;
+ public const int TLS_DHE_RSA_WITH_AES_128_CCM_8 = 0xC0A2;
+ public const int TLS_DHE_RSA_WITH_AES_256_CCM_8 = 0xC0A3;
+ public const int TLS_PSK_WITH_AES_128_CCM = 0xC0A4;
+ public const int TLS_PSK_WITH_AES_256_CCM = 0xC0A5;
+ public const int TLS_DHE_PSK_WITH_AES_128_CCM = 0xC0A6;
+ public const int TLS_DHE_PSK_WITH_AES_256_CCM = 0xC0A7;
+ public const int TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8;
+ public const int TLS_PSK_WITH_AES_256_CCM_8 = 0xC0A9;
+ public const int TLS_PSK_DHE_WITH_AES_128_CCM_8 = 0xC0AA;
+ public const int TLS_PSK_DHE_WITH_AES_256_CCM_8 = 0xC0AB;
+
+ /*
+ * TBD[draft-josefsson-salsa20-tls-02]
+ */
+ const int TLS_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF00;
+ const int TLS_RSA_WITH_SALSA20_SHA1 = 0xFF01;
+ const int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF02;
+ const int TLS_DHE_RSA_WITH_SALSA20_SHA1 = 0xFF03;
+ const int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF04;
+ const int TLS_ECDHE_RSA_WITH_SALSA20_SHA1 = 0xFF05;
+ const int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF06;
+ const int TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1 = 0xFF07;
+ const int TLS_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF08;
+ const int TLS_PSK_WITH_SALSA20_SHA1 = 0xFF09;
+ const int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF0A;
+ const int TLS_DHE_PSK_WITH_SALSA20_SHA1 = 0xFF0B;
+ const int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF0C;
+ const int TLS_RSA_PSK_WITH_SALSA20_SHA1 = 0xFF0D;
+ const int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF0E;
+ const int TLS_ECDHE_PSK_WITH_SALSA20_SHA1 = 0xFF0F;
+ const int TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF10;
+ const int TLS_RSA_WITH_SALSA20_UMAC96 = 0xFF11;
+ const int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF12;
+ const int TLS_DHE_RSA_WITH_SALSA20_UMAC96 = 0xFF13;
+ const int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF14;
+ const int TLS_ECDHE_RSA_WITH_SALSA20_UMAC96 = 0xFF15;
+ const int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF16;
+ const int TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96 = 0xFF17;
+ const int TLS_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF18;
+ const int TLS_PSK_WITH_SALSA20_UMAC96 = 0xFF19;
+ const int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF1A;
+ const int TLS_DHE_PSK_WITH_SALSA20_UMAC96 = 0xFF1B;
+ const int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF1C;
+ const int TLS_RSA_PSK_WITH_SALSA20_UMAC96 = 0xFF1D;
+ const int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF1E;
+ const int TLS_ECDHE_PSK_WITH_SALSA20_UMAC96 = 0xFF1F;
+ }
}
diff --git a/crypto/src/crypto/tls/ClientCertificateType.cs b/crypto/src/crypto/tls/ClientCertificateType.cs
index 58f5d4276..a291a46e6 100644
--- a/crypto/src/crypto/tls/ClientCertificateType.cs
+++ b/crypto/src/crypto/tls/ClientCertificateType.cs
@@ -1,20 +1,23 @@
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 2246 7.4.4
- /// </summary>
- public enum ClientCertificateType : byte
- {
- rsa_sign = 1,
- dss_sign = 2,
- rsa_fixed_dh = 3,
- dss_fixed_dh = 4,
+ public abstract class ClientCertificateType
+ {
+ /*
+ * RFC 4346 7.4.4
+ */
+ public const byte rsa_sign = 1;
+ public const byte dss_sign = 2;
+ public const byte rsa_fixed_dh = 3;
+ public const byte dss_fixed_dh = 4;
+ public const byte rsa_ephemeral_dh_RESERVED = 5;
+ public const byte dss_ephemeral_dh_RESERVED = 6;
+ public const byte fortezza_dms_RESERVED = 20;
- /*
- * RFC 4492 5.5
- */
- ecdsa_sign = 64,
- rsa_fixed_ecdh = 65,
- ecdsa_fixed_ecdh = 66,
- }
-}
\ No newline at end of file
+ /*
+ * RFC 4492 5.5
+ */
+ public const byte ecdsa_sign = 64;
+ public const byte rsa_fixed_ecdh = 65;
+ public const byte ecdsa_fixed_ecdh = 66;
+ }
+}
diff --git a/crypto/src/crypto/tls/CompressionMethod.cs b/crypto/src/crypto/tls/CompressionMethod.cs
index 4a127a63e..e4ee9666f 100644
--- a/crypto/src/crypto/tls/CompressionMethod.cs
+++ b/crypto/src/crypto/tls/CompressionMethod.cs
@@ -1,20 +1,22 @@
+using System;
+
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 2246 6.1
- /// </summary>
- public enum CompressionMethod : byte
- {
- NULL = 0,
+ /// <summary>
+ /// RFC 2246 6.1
+ /// </summary>
+ public abstract class CompressionMethod
+ {
+ public const byte NULL = 0;
- /*
- * RFC 3749 2
- */
- DEFLATE = 1
+ /*
+ * RFC 3749 2
+ */
+ public const byte DEFLATE = 1;
- /*
- * Values from 224 decimal (0xE0) through 255 decimal (0xFF)
- * inclusive are reserved for private use.
- */
- }
+ /*
+ * Values from 224 decimal (0xE0) through 255 decimal (0xFF)
+ * inclusive are reserved for private use.
+ */
+ }
}
diff --git a/crypto/src/crypto/tls/ContentType.cs b/crypto/src/crypto/tls/ContentType.cs
index a664e3a38..d6ab43857 100644
--- a/crypto/src/crypto/tls/ContentType.cs
+++ b/crypto/src/crypto/tls/ContentType.cs
@@ -1,13 +1,14 @@
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 2246 6.2.1
- /// </summary>
- public enum ContentType : byte
- {
- change_cipher_spec = 20,
- alert = 21,
- handshake = 22,
- application_data = 23,
- }
+ /**
+ * RFC 2246 6.2.1
+ */
+ public abstract class ContentType
+ {
+ public const byte change_cipher_spec = 20;
+ public const byte alert = 21;
+ public const byte handshake = 22;
+ public const byte application_data = 23;
+ public const byte heartbeat = 24;
+ }
}
diff --git a/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs b/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs
index 130f4c589..2bd2f40bf 100644
--- a/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs
+++ b/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs
@@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Crypto.Tls
{
throw new ArgumentNullException("clientCertificate");
}
- if (clientCertificate.certs.Length == 0)
+ if (clientCertificate.Length == 0)
{
throw new ArgumentException("cannot be empty", "clientCertificate");
}
diff --git a/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
index 75ae311e1..9b6e2c14c 100644
--- a/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
+++ b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
@@ -7,26 +7,26 @@ using Org.BouncyCastle.Crypto.Modes;
namespace Org.BouncyCastle.Crypto.Tls
{
- public class DefaultTlsCipherFactory
- : TlsCipherFactory
- {
- public virtual TlsCipher CreateCipher(TlsClientContext context,
- EncryptionAlgorithm encryptionAlgorithm, DigestAlgorithm digestAlgorithm)
- {
- switch (encryptionAlgorithm)
- {
- case EncryptionAlgorithm.cls_3DES_EDE_CBC:
- return CreateDesEdeCipher(context, 24, digestAlgorithm);
- case EncryptionAlgorithm.AES_128_CBC:
- return CreateAesCipher(context, 16, digestAlgorithm);
- case EncryptionAlgorithm.AES_256_CBC:
- return CreateAesCipher(context, 32, digestAlgorithm);
+ public class DefaultTlsCipherFactory
+ : TlsCipherFactory
+ {
+ public virtual TlsCipher CreateCipher(TlsClientContext context,
+ int encryptionAlgorithm, DigestAlgorithm digestAlgorithm)
+ {
+ switch (encryptionAlgorithm)
+ {
+ case EncryptionAlgorithm.cls_3DES_EDE_CBC:
+ return CreateDesEdeCipher(context, 24, digestAlgorithm);
+ case EncryptionAlgorithm.AES_128_CBC:
+ return CreateAesCipher(context, 16, digestAlgorithm);
+ case EncryptionAlgorithm.AES_256_CBC:
+ return CreateAesCipher(context, 32, digestAlgorithm);
case EncryptionAlgorithm.RC4_128:
return CreateRC4Cipher(context, 16, digestAlgorithm);
- default:
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
/// <exception cref="IOException"></exception>
protected virtual TlsCipher CreateRC4Cipher(TlsClientContext context, int cipherKeySize, DigestAlgorithm digestAlgorithm)
@@ -34,53 +34,53 @@ namespace Org.BouncyCastle.Crypto.Tls
return new TlsStreamCipher(context, CreateRC4StreamCipher(), CreateRC4StreamCipher(), CreateDigest(digestAlgorithm), CreateDigest(digestAlgorithm), cipherKeySize);
}
- /// <exception cref="IOException"></exception>
- protected virtual TlsCipher CreateAesCipher(TlsClientContext context, int cipherKeySize,
- DigestAlgorithm digestAlgorithm)
- {
- return new TlsBlockCipher(context, CreateAesBlockCipher(), CreateAesBlockCipher(),
- CreateDigest(digestAlgorithm), CreateDigest(digestAlgorithm), cipherKeySize);
- }
+ /// <exception cref="IOException"></exception>
+ protected virtual TlsCipher CreateAesCipher(TlsClientContext context, int cipherKeySize,
+ DigestAlgorithm digestAlgorithm)
+ {
+ return new TlsBlockCipher(context, CreateAesBlockCipher(), CreateAesBlockCipher(),
+ CreateDigest(digestAlgorithm), CreateDigest(digestAlgorithm), cipherKeySize);
+ }
- /// <exception cref="IOException"></exception>
- protected virtual TlsCipher CreateDesEdeCipher(TlsClientContext context, int cipherKeySize,
- DigestAlgorithm digestAlgorithm)
- {
- return new TlsBlockCipher(context, CreateDesEdeBlockCipher(), CreateDesEdeBlockCipher(),
- CreateDigest(digestAlgorithm), CreateDigest(digestAlgorithm), cipherKeySize);
- }
+ /// <exception cref="IOException"></exception>
+ protected virtual TlsCipher CreateDesEdeCipher(TlsClientContext context, int cipherKeySize,
+ DigestAlgorithm digestAlgorithm)
+ {
+ return new TlsBlockCipher(context, CreateDesEdeBlockCipher(), CreateDesEdeBlockCipher(),
+ CreateDigest(digestAlgorithm), CreateDigest(digestAlgorithm), cipherKeySize);
+ }
protected virtual IStreamCipher CreateRC4StreamCipher()
{
return new RC4Engine();
}
- protected virtual IBlockCipher CreateAesBlockCipher()
- {
- return new CbcBlockCipher(new AesFastEngine());
- }
+ protected virtual IBlockCipher CreateAesBlockCipher()
+ {
+ return new CbcBlockCipher(new AesFastEngine());
+ }
- protected virtual IBlockCipher CreateDesEdeBlockCipher()
- {
- return new CbcBlockCipher(new DesEdeEngine());
- }
+ protected virtual IBlockCipher CreateDesEdeBlockCipher()
+ {
+ return new CbcBlockCipher(new DesEdeEngine());
+ }
- /// <exception cref="IOException"></exception>
- protected virtual IDigest CreateDigest(DigestAlgorithm digestAlgorithm)
- {
- switch (digestAlgorithm)
- {
- case DigestAlgorithm.MD5:
- return new MD5Digest();
- case DigestAlgorithm.SHA:
- return new Sha1Digest();
- case DigestAlgorithm.SHA256:
- return new Sha256Digest();
- case DigestAlgorithm.SHA384:
- return new Sha384Digest();
- default:
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
- }
+ /// <exception cref="IOException"></exception>
+ protected virtual IDigest CreateDigest(DigestAlgorithm digestAlgorithm)
+ {
+ switch (digestAlgorithm)
+ {
+ case DigestAlgorithm.MD5:
+ return new MD5Digest();
+ case DigestAlgorithm.SHA:
+ return new Sha1Digest();
+ case DigestAlgorithm.SHA256:
+ return new Sha256Digest();
+ case DigestAlgorithm.SHA384:
+ return new Sha384Digest();
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs
index 9f30a33f4..a5fbe8235 100644
--- a/crypto/src/crypto/tls/DefaultTlsClient.cs
+++ b/crypto/src/crypto/tls/DefaultTlsClient.cs
@@ -11,125 +11,125 @@ using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Tls
{
- public abstract class DefaultTlsClient
- : TlsClient
- {
- protected TlsCipherFactory cipherFactory;
-
- protected TlsClientContext context;
-
- protected CompressionMethod selectedCompressionMethod;
- protected CipherSuite selectedCipherSuite;
-
- public DefaultTlsClient()
- : this(new DefaultTlsCipherFactory())
- {
- }
-
- public DefaultTlsClient(TlsCipherFactory cipherFactory)
- {
- this.cipherFactory = cipherFactory;
- }
-
- public virtual void Init(TlsClientContext context)
- {
- this.context = context;
- }
-
- public virtual CipherSuite[] GetCipherSuites()
- {
- return new CipherSuite[] {
- CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
- CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
- CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ public abstract class DefaultTlsClient
+ : TlsClient
+ {
+ protected TlsCipherFactory cipherFactory;
+
+ protected TlsClientContext context;
+
+ protected byte selectedCompressionMethod;
+ protected int selectedCipherSuite;
+
+ public DefaultTlsClient()
+ : this(new DefaultTlsCipherFactory())
+ {
+ }
+
+ public DefaultTlsClient(TlsCipherFactory cipherFactory)
+ {
+ this.cipherFactory = cipherFactory;
+ }
+
+ public virtual void Init(TlsClientContext context)
+ {
+ this.context = context;
+ }
+
+ public virtual int[] GetCipherSuites()
+ {
+ return new int[] {
+ CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
CipherSuite.TLS_RSA_WITH_RC4_128_SHA,
- };
- }
+ };
+ }
- public virtual CompressionMethod[] GetCompressionMethods()
+ public virtual byte[] GetCompressionMethods()
{
- /*
- * To offer DEFLATE compression, override this method:
- * return new CompressionMethod[] { CompressionMethod.DEFLATE, CompressionMethod.NULL };
- */
+ /*
+ * To offer DEFLATE compression, override this method:
+ * return new byte[] { CompressionMethod.DEFLATE, CompressionMethod.NULL };
+ */
- return new CompressionMethod[] { CompressionMethod.NULL };
+ return new byte[] { CompressionMethod.NULL };
}
public virtual IDictionary GetClientExtensions()
- {
- return null;
- }
+ {
+ return null;
+ }
public virtual void NotifySessionID(byte[] sessionID)
- {
- // Currently ignored
- }
+ {
+ // Currently ignored
+ }
- public virtual void NotifySelectedCipherSuite(CipherSuite selectedCipherSuite)
- {
- this.selectedCipherSuite = selectedCipherSuite;
- }
+ public virtual void NotifySelectedCipherSuite(int selectedCipherSuite)
+ {
+ this.selectedCipherSuite = selectedCipherSuite;
+ }
- public virtual void NotifySelectedCompressionMethod(CompressionMethod selectedCompressionMethod)
+ public virtual void NotifySelectedCompressionMethod(byte selectedCompressionMethod)
{
this.selectedCompressionMethod = selectedCompressionMethod;
}
public virtual void NotifySecureRenegotiation(bool secureRenegotiation)
- {
- if (!secureRenegotiation)
- {
- /*
- * RFC 5746 3.4.
- * If the extension is not present, the server does not support
- * secure renegotiation; set secure_renegotiation flag to FALSE.
- * In this case, some clients may want to terminate the handshake
- * instead of continuing; see Section 4.1 for discussion.
- */
+ {
+ if (!secureRenegotiation)
+ {
+ /*
+ * RFC 5746 3.4.
+ * If the extension is not present, the server does not support
+ * secure renegotiation; set secure_renegotiation flag to FALSE.
+ * In this case, some clients may want to terminate the handshake
+ * instead of continuing; see Section 4.1 for discussion.
+ */
// throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
+ }
+ }
public virtual void ProcessServerExtensions(IDictionary serverExtensions)
- {
- }
+ {
+ }
public virtual TlsKeyExchange GetKeyExchange()
- {
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
- return CreateRsaKeyExchange();
+ return CreateRsaKeyExchange();
- case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
+ case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
- case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
- return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
+ case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
- case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
- return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
+ case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
- case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
- return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
+ case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
@@ -155,54 +155,54 @@ namespace Org.BouncyCastle.Crypto.Tls
case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA);
- default:
- /*
- * Note: internal error here; the TlsProtocolHandler verifies that the
- * server-selected cipher suite was in the list of client-offered cipher
- * suites, so if we now can't produce an implementation, we shouldn't have
- * offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public abstract TlsAuthentication GetAuthentication();
-
- public virtual TlsCompression GetCompression()
- {
- switch (selectedCompressionMethod)
- {
- case CompressionMethod.NULL:
- return new TlsNullCompression();
-
- case CompressionMethod.DEFLATE:
- return new TlsDeflateCompression();
-
- default:
- /*
- * Note: internal error here; the TlsProtocolHandler verifies that the
- * server-selected compression method was in the list of client-offered compression
- * methods, so if we now can't produce an implementation, we shouldn't have
- * offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public virtual TlsCipher GetCipher()
- {
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public abstract TlsAuthentication GetAuthentication();
+
+ public virtual TlsCompression GetCompression()
+ {
+ switch (selectedCompressionMethod)
+ {
+ case CompressionMethod.NULL:
+ return new TlsNullCompression();
+
+ case CompressionMethod.DEFLATE:
+ return new TlsDeflateCompression();
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected compression method was in the list of client-offered compression
+ * methods, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public virtual TlsCipher GetCipher()
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- return cipherFactory.CreateCipher(context, EncryptionAlgorithm.cls_3DES_EDE_CBC, DigestAlgorithm.SHA);
+ return cipherFactory.CreateCipher(context, EncryptionAlgorithm.cls_3DES_EDE_CBC, DigestAlgorithm.SHA);
case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
@@ -212,61 +212,61 @@ namespace Org.BouncyCastle.Crypto.Tls
return cipherFactory.CreateCipher(context, EncryptionAlgorithm.RC4_128, DigestAlgorithm.SHA);
case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_128_CBC, DigestAlgorithm.SHA);
+ return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_128_CBC, DigestAlgorithm.SHA);
- case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_256_CBC, DigestAlgorithm.SHA);
-
- default:
- /*
- * Note: internal error here; the TlsProtocolHandler verifies that the
- * server-selected cipher suite was in the list of client-offered cipher
- * suites, so if we now can't produce an implementation, we shouldn't have
- * offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected virtual TlsKeyExchange CreateDHKeyExchange(KeyExchangeAlgorithm keyExchange)
- {
- return new TlsDHKeyExchange(context, keyExchange);
- }
-
- protected virtual TlsKeyExchange CreateDheKeyExchange(KeyExchangeAlgorithm keyExchange)
- {
- return new TlsDheKeyExchange(context, keyExchange);
- }
-
- protected virtual TlsKeyExchange CreateECDHKeyExchange(KeyExchangeAlgorithm keyExchange)
+ return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_256_CBC, DigestAlgorithm.SHA);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
+ {
+ return new TlsDHKeyExchange(context, keyExchange);
+ }
+
+ protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
+ {
+ return new TlsDheKeyExchange(context, keyExchange);
+ }
+
+ protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
{
return new TlsECDHKeyExchange(context, keyExchange);
}
- protected virtual TlsKeyExchange CreateECDheKeyExchange(KeyExchangeAlgorithm keyExchange)
+ protected virtual TlsKeyExchange CreateECDheKeyExchange(int keyExchange)
{
return new TlsECDheKeyExchange(context, keyExchange);
}
protected virtual TlsKeyExchange CreateRsaKeyExchange()
- {
- return new TlsRsaKeyExchange(context);
- }
+ {
+ return new TlsRsaKeyExchange(context);
+ }
}
}
diff --git a/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs b/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs
index 86c9d1a18..2c5aa3524 100644
--- a/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs
+++ b/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs
@@ -20,7 +20,7 @@ namespace Org.BouncyCastle.Crypto.Tls
{
throw new ArgumentNullException("clientCertificate");
}
- if (clientCertificate.certs.Length == 0)
+ if (clientCertificate.Length == 0)
{
throw new ArgumentException("cannot be empty", "clientCertificate");
}
diff --git a/crypto/src/crypto/tls/ECCurveType.cs b/crypto/src/crypto/tls/ECCurveType.cs
index 15d5d7b42..1b352e9c4 100644
--- a/crypto/src/crypto/tls/ECCurveType.cs
+++ b/crypto/src/crypto/tls/ECCurveType.cs
@@ -1,29 +1,29 @@
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 4492 5.4
- /// </summary>
- public enum ECCurveType : byte
- {
- /**
- * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
- * underlying finite field is a prime field.
- */
- explicit_prime = 1,
+ /// <summary>
+ /// RFC 4492 5.4
+ /// </summary>
+ public abstract class ECCurveType
+ {
+ /**
+ * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+ * underlying finite field is a prime field.
+ */
+ public const byte explicit_prime = 1;
- /**
- * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
- * underlying finite field is a characteristic-2 field.
- */
- explicit_char2 = 2,
+ /**
+ * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+ * underlying finite field is a characteristic-2 field.
+ */
+ public const byte explicit_char2 = 2;
- /**
- * Indicates that a named curve is used. This option SHOULD be used when applicable.
- */
- named_curve = 3,
+ /**
+ * Indicates that a named curve is used. This option SHOULD be used when applicable.
+ */
+ public const byte named_curve = 3;
- /*
- * Values 248 through 255 are reserved for private use.
- */
- }
+ /*
+ * Values 248 through 255 are reserved for private use.
+ */
+ }
}
diff --git a/crypto/src/crypto/tls/ECPointFormat.cs b/crypto/src/crypto/tls/ECPointFormat.cs
index 4e0dd0067..21b0fdd97 100644
--- a/crypto/src/crypto/tls/ECPointFormat.cs
+++ b/crypto/src/crypto/tls/ECPointFormat.cs
@@ -1,16 +1,16 @@
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 4492 5.1.2
- /// </summary>
- public enum ECPointFormat : byte
- {
- uncompressed = 0,
- ansiX962_compressed_prime = 1,
- ansiX962_compressed_char2 = 2,
+ /// <summary>
+ /// RFC 4492 5.1.2
+ /// </summary>
+ public abstract class ECPointFormat
+ {
+ public const byte uncompressed = 0;
+ public const byte ansiX962_compressed_prime = 1;
+ public const byte ansiX962_compressed_char2 = 2;
- /*
- * reserved (248..255)
- */
- }
+ /*
+ * reserved (248..255)
+ */
+ }
}
diff --git a/crypto/src/crypto/tls/EncryptionAlgorithm.cs b/crypto/src/crypto/tls/EncryptionAlgorithm.cs
index 79d3b63b5..69aee8abc 100644
--- a/crypto/src/crypto/tls/EncryptionAlgorithm.cs
+++ b/crypto/src/crypto/tls/EncryptionAlgorithm.cs
@@ -2,31 +2,58 @@ using System;
namespace Org.BouncyCastle.Crypto.Tls
{
- public enum EncryptionAlgorithm
- {
- /*
- * Note that the values here are implementation-specific and arbitrary.
- * It is recommended not to depend on the particular values (e.g. serialization).
- */
- NULL,
- RC4_40,
- RC4_128,
- RC2_CBC_40,
- IDEA_CBC,
- DES40_CBC,
- DES_CBC,
- cls_3DES_EDE_CBC,
+ /**
+ * RFC 2246
+ * <p/>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+ public abstract class EncryptionAlgorithm
+ {
+ public const int NULL = 0;
+ public const int RC4_40 = 1;
+ public const int RC4_128 = 2;
+ public const int RC2_CBC_40 = 3;
+ public const int IDEA_CBC = 4;
+ public const int DES40_CBC = 5;
+ public const int DES_CBC = 6;
+ public const int cls_3DES_EDE_CBC = 7;
- /*
- * RFC 3268
- */
- AES_128_CBC,
- AES_256_CBC,
+ /*
+ * RFC 3268
+ */
+ public const int AES_128_CBC = 8;
+ public const int AES_256_CBC = 9;
- /*
- * RFC 5289
- */
- AES_128_GCM,
- AES_256_GCM,
- }
+ /*
+ * RFC 5289
+ */
+ public const int AES_128_GCM = 10;
+ public const int AES_256_GCM = 11;
+
+ /*
+ * RFC 4132
+ */
+ public const int CAMELLIA_128_CBC = 12;
+ public const int CAMELLIA_256_CBC = 13;
+
+ /*
+ * RFC 4162
+ */
+ public const int SEED_CBC = 14;
+
+ /*
+ * RFC 6655
+ */
+ public const int AES_128_CCM = 15;
+ public const int AES_128_CCM_8 = 16;
+ public const int AES_256_CCM = 17;
+ public const int AES_256_CCM_8 = 18;
+
+ /*
+ * TBD[draft-josefsson-salsa20-tls-02]
+ */
+ const int ESTREAM_SALSA20 = 100;
+ const int SALSA20 = 101;
+ }
}
diff --git a/crypto/src/crypto/tls/ExtensionType.cs b/crypto/src/crypto/tls/ExtensionType.cs
index f00e34e3f..0e6a45b5e 100644
--- a/crypto/src/crypto/tls/ExtensionType.cs
+++ b/crypto/src/crypto/tls/ExtensionType.cs
@@ -1,31 +1,56 @@
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 4366 2.3
- /// </summary>
- public enum ExtensionType : int
- {
- server_name = 0,
- max_fragment_length = 1,
- client_certificate_url = 2,
- trusted_ca_keys = 3,
- truncated_hmac = 4,
- status_request = 5,
-
- /*
- * RFC 4492
- */
- elliptic_curves = 10,
- ec_point_formats = 11,
-
- /*
- * RFC 5054 2.8.1
- */
- srp = 12,
-
- /*
- * RFC 5746 6
- */
- renegotiation_info = 0xff01,
- }
+ public abstract class ExtensionType
+ {
+ /*
+ * RFC 2546 2.3.
+ */
+ public const int server_name = 0;
+ public const int max_fragment_length = 1;
+ public const int client_certificate_url = 2;
+ public const int trusted_ca_keys = 3;
+ public const int truncated_hmac = 4;
+ public const int status_request = 5;
+
+ /*
+ * RFC 4681
+ */
+ public const int user_mapping = 6;
+
+ /*
+ * RFC 4492 5.1.
+ */
+ public const int elliptic_curves = 10;
+ public const int ec_point_formats = 11;
+
+ /*
+ * RFC 5054 2.8.1.
+ */
+ public const int srp = 12;
+
+ /*
+ * RFC 5077 7.
+ */
+ public const int session_ticket = 35;
+
+ /*
+ * RFC 5246 7.4.1.4.
+ */
+ public const int signature_algorithms = 13;
+
+ /*
+ * RFC 5764 9.
+ */
+ public const int use_srtp = 14;
+
+ /*
+ * RFC 6520 6.
+ */
+ public const int heartbeat = 15;
+
+ /*
+ * RFC 5746 3.2.
+ */
+ public const int renegotiation_info = 0xff01;
+ }
}
diff --git a/crypto/src/crypto/tls/HandshakeType.cs b/crypto/src/crypto/tls/HandshakeType.cs
index deedb1f84..e63042ac3 100644
--- a/crypto/src/crypto/tls/HandshakeType.cs
+++ b/crypto/src/crypto/tls/HandshakeType.cs
@@ -1,19 +1,40 @@
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 2246 7.4
- /// </summary>
- public enum HandshakeType : byte
- {
- hello_request = 0,
- client_hello = 1,
- server_hello = 2,
- certificate = 11,
- server_key_exchange = 12,
- certificate_request = 13,
- server_hello_done = 14,
- certificate_verify = 15,
- client_key_exchange = 16,
- finished = 20,
- }
+ public abstract class HandshakeType
+ {
+ /*
+ * RFC 2246 7.4
+ */
+ public const byte hello_request = 0;
+ public const byte client_hello = 1;
+ public const byte server_hello = 2;
+ public const byte certificate = 11;
+ public const byte server_key_exchange = 12;
+ public const byte certificate_request = 13;
+ public const byte server_hello_done = 14;
+ public const byte certificate_verify = 15;
+ public const byte client_key_exchange = 16;
+ public const byte finished = 20;
+
+ /*
+ * RFC 3546 2.4
+ */
+ public const byte certificate_url = 21;
+ public const byte certificate_status = 22;
+
+ /*
+ * (DTLS) RFC 4347 4.3.2
+ */
+ public const byte hello_verify_request = 3;
+
+ /*
+ * RFC 4680
+ */
+ public const byte supplemental_data = 23;
+
+ /*
+ * RFC 5077
+ */
+ public const byte session_ticket = 4;
+ }
}
diff --git a/crypto/src/crypto/tls/HashAlgorithm.cs b/crypto/src/crypto/tls/HashAlgorithm.cs
new file mode 100644
index 000000000..41818ca2c
--- /dev/null
+++ b/crypto/src/crypto/tls/HashAlgorithm.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ /**
+ * RFC 5246 7.4.1.4.1
+ */
+ public abstract class HashAlgorithm
+ {
+ public const byte none = 0;
+ public const byte md5 = 1;
+ public const byte sha1 = 2;
+ public const byte sha224 = 3;
+ public const byte sha256 = 4;
+ public const byte sha384 = 5;
+ public const byte sha512 = 6;
+ }
+}
diff --git a/crypto/src/crypto/tls/KeyExchangeAlgorithm.cs b/crypto/src/crypto/tls/KeyExchangeAlgorithm.cs
index 3fdbeb2a6..3f5088d9b 100644
--- a/crypto/src/crypto/tls/KeyExchangeAlgorithm.cs
+++ b/crypto/src/crypto/tls/KeyExchangeAlgorithm.cs
@@ -2,35 +2,54 @@ using System;
namespace Org.BouncyCastle.Crypto.Tls
{
- public enum KeyExchangeAlgorithm
- {
- /*
- * Note that the values here are implementation-specific and arbitrary.
- * It is recommended not to depend on the particular values (e.g. serialization).
- */
- NULL,
- RSA,
- RSA_EXPORT,
- DHE_DSS,
- DHE_DSS_EXPORT,
- DHE_RSA,
- DHE_RSA_EXPORT,
- DH_DSS,
- DH_DSS_EXPORT,
- DH_RSA,
- DH_RSA_EXPORT,
- DH_anon,
- DH_anon_export,
- PSK,
- DHE_PSK,
- RSA_PSK,
- ECDH_ECDSA,
- ECDHE_ECDSA,
- ECDH_RSA,
- ECDHE_RSA,
- ECDH_anon,
- SRP,
- SRP_DSS,
- SRP_RSA,
- }
+ /**
+ * RFC 2246
+ * <p/>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+ public abstract class KeyExchangeAlgorithm
+ {
+ public const int NULL = 0;
+ public const int RSA = 1;
+ public const int RSA_EXPORT = 2;
+ public const int DHE_DSS = 3;
+ public const int DHE_DSS_EXPORT = 4;
+ public const int DHE_RSA = 5;
+ public const int DHE_RSA_EXPORT = 6;
+ public const int DH_DSS = 7;
+ public const int DH_DSS_EXPORT = 8;
+ public const int DH_RSA = 9;
+ public const int DH_RSA_EXPORT = 10;
+ public const int DH_anon = 11;
+ public const int DH_anon_EXPORT = 12;
+
+ /*
+ * RFC 4279
+ */
+ public const int PSK = 13;
+ public const int DHE_PSK = 14;
+ public const int RSA_PSK = 15;
+
+ /*
+ * RFC 4429
+ */
+ public const int ECDH_ECDSA = 16;
+ public const int ECDHE_ECDSA = 17;
+ public const int ECDH_RSA = 18;
+ public const int ECDHE_RSA = 19;
+ public const int ECDH_anon = 20;
+
+ /*
+ * RFC 5054
+ */
+ public const int SRP = 21;
+ public const int SRP_DSS = 22;
+ public const int SRP_RSA = 23;
+
+ /*
+ * RFC 5489
+ */
+ public const int ECDHE_PSK = 24;
+ }
}
diff --git a/crypto/src/crypto/tls/LegacyTlsAuthentication.cs b/crypto/src/crypto/tls/LegacyTlsAuthentication.cs
index 395f94208..bce31c0b0 100644
--- a/crypto/src/crypto/tls/LegacyTlsAuthentication.cs
+++ b/crypto/src/crypto/tls/LegacyTlsAuthentication.cs
@@ -2,29 +2,29 @@ using System;
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// A temporary class to wrap old CertificateVerifyer stuff for new TlsAuthentication.
- /// </summary>
- [Obsolete]
- public class LegacyTlsAuthentication
- : TlsAuthentication
- {
- protected ICertificateVerifyer verifyer;
+ /// <summary>
+ /// A temporary class to wrap old CertificateVerifyer stuff for new TlsAuthentication.
+ /// </summary>
+ [Obsolete]
+ public class LegacyTlsAuthentication
+ : TlsAuthentication
+ {
+ protected ICertificateVerifyer verifyer;
- public LegacyTlsAuthentication(ICertificateVerifyer verifyer)
- {
- this.verifyer = verifyer;
- }
+ public LegacyTlsAuthentication(ICertificateVerifyer verifyer)
+ {
+ this.verifyer = verifyer;
+ }
- public virtual void NotifyServerCertificate(Certificate serverCertificate)
- {
- if (!this.verifyer.IsValid(serverCertificate.GetCerts()))
- throw new TlsFatalAlert(AlertDescription.user_canceled);
- }
+ public virtual void NotifyServerCertificate(Certificate serverCertificate)
+ {
+ if (!this.verifyer.IsValid(serverCertificate.GetCertificateList()))
+ throw new TlsFatalAlert(AlertDescription.user_canceled);
+ }
- public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
- {
- return null;
- }
- }
+ public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
+ {
+ return null;
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/NamedCurve.cs b/crypto/src/crypto/tls/NamedCurve.cs
index c8ee189aa..8ef395069 100644
--- a/crypto/src/crypto/tls/NamedCurve.cs
+++ b/crypto/src/crypto/tls/NamedCurve.cs
@@ -6,67 +6,91 @@ using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// RFC 4492 5.1.1
- /// The named curves defined here are those specified in SEC 2 [13]. Note that many of
- /// these curves are also recommended in ANSI X9.62 [7] and FIPS 186-2 [11]. Values 0xFE00
- /// through 0xFEFF are reserved for private use. Values 0xFF01 and 0xFF02 indicate that the
- /// client supports arbitrary prime and characteristic-2 curves, respectively (the curve
- /// parameters must be encoded explicitly in ECParameters).
- /// </summary>
- public enum NamedCurve : int
- {
- sect163k1 = 1,
- sect163r1 = 2,
- sect163r2 = 3,
- sect193r1 = 4,
- sect193r2 = 5,
- sect233k1 = 6,
- sect233r1 = 7,
- sect239k1 = 8,
- sect283k1 = 9,
- sect283r1 = 10,
- sect409k1 = 11,
- sect409r1 = 12,
- sect571k1 = 13,
- sect571r1 = 14,
- secp160k1 = 15,
- secp160r1 = 16,
- secp160r2 = 17,
- secp192k1 = 18,
- secp192r1 = 19,
- secp224k1 = 20,
- secp224r1 = 21,
- secp256k1 = 22,
- secp256r1 = 23,
- secp384r1 = 24,
- secp521r1 = 25,
+ /// <summary>
+ /// RFC 4492 5.1.1
+ /// The named curves defined here are those specified in SEC 2 [13]. Note that many of
+ /// these curves are also recommended in ANSI X9.62 [7] and FIPS 186-2 [11]. Values 0xFE00
+ /// through 0xFEFF are reserved for private use. Values 0xFF01 and 0xFF02 indicate that the
+ /// client supports arbitrary prime and characteristic-2 curves, respectively (the curve
+ /// parameters must be encoded explicitly in ECParameters).
+ /// </summary>
+ public abstract class NamedCurve
+ {
+ public const int sect163k1 = 1;
+ public const int sect163r1 = 2;
+ public const int sect163r2 = 3;
+ public const int sect193r1 = 4;
+ public const int sect193r2 = 5;
+ public const int sect233k1 = 6;
+ public const int sect233r1 = 7;
+ public const int sect239k1 = 8;
+ public const int sect283k1 = 9;
+ public const int sect283r1 = 10;
+ public const int sect409k1 = 11;
+ public const int sect409r1 = 12;
+ public const int sect571k1 = 13;
+ public const int sect571r1 = 14;
+ public const int secp160k1 = 15;
+ public const int secp160r1 = 16;
+ public const int secp160r2 = 17;
+ public const int secp192k1 = 18;
+ public const int secp192r1 = 19;
+ public const int secp224k1 = 20;
+ public const int secp224r1 = 21;
+ public const int secp256k1 = 22;
+ public const int secp256r1 = 23;
+ public const int secp384r1 = 24;
+ public const int secp521r1 = 25;
+
+ /*
+ * RFC 7027
+ */
+ public const int brainpoolP256r1 = 26;
+ public const int brainpoolP384r1 = 27;
+ public const int brainpoolP512r1 = 28;
- /*
- * reserved (0xFE00..0xFEFF)
- */
+ /*
+ * reserved (0xFE00..0xFEFF)
+ */
- arbitrary_explicit_prime_curves = 0xFF01,
- arbitrary_explicit_char2_curves = 0xFF02,
- }
+ public const int arbitrary_explicit_prime_curves = 0xFF01;
+ public const int arbitrary_explicit_char2_curves = 0xFF02;
- internal class NamedCurveHelper
- {
- internal static ECDomainParameters GetECParameters(NamedCurve namedCurve)
- {
- if (!Enum.IsDefined(typeof(NamedCurve), namedCurve))
+ public static bool IsValid(int namedCurve)
+ {
+ return namedCurve >= sect163k1 && namedCurve <= brainpoolP512r1;
+ }
+
+ public static bool RefersToASpecificNamedCurve(int namedCurve)
+ {
+ switch (namedCurve)
+ {
+ case arbitrary_explicit_prime_curves:
+ case arbitrary_explicit_char2_curves:
+ return false;
+ default:
+ return true;
+ }
+ }
+ }
+
+ internal class NamedCurveHelper
+ {
+ internal static ECDomainParameters GetECParameters(int namedCurve)
+ {
+ if (!NamedCurve.IsValid(namedCurve))
return null;
string curveName = namedCurve.ToString();
// Lazily created the first time a particular curve is accessed
- X9ECParameters ecP = SecNamedCurves.GetByName(curveName);
+ X9ECParameters ecP = SecNamedCurves.GetByName(curveName);
if (ecP == null)
return null;
- // It's a bit inefficient to do this conversion every time
- return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
- }
- }
+ // It's a bit inefficient to do this conversion every time
+ return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/PrfAlgorithm.cs b/crypto/src/crypto/tls/PrfAlgorithm.cs
new file mode 100644
index 000000000..976113495
--- /dev/null
+++ b/crypto/src/crypto/tls/PrfAlgorithm.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ /**
+ * RFC 5246
+ * <p/>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+ public abstract class PrfAlgorithm
+ {
+ /*
+ * Placeholder to refer to the legacy TLS algorithm
+ */
+ public const int tls_prf_legacy = 0;
+
+ public const int tls_prf_sha256 = 1;
+
+ /*
+ * Implied by RFC 5288
+ */
+ public const int tls_prf_sha384 = 2;
+ }
+}
diff --git a/crypto/src/crypto/tls/ProtocolVersion.cs b/crypto/src/crypto/tls/ProtocolVersion.cs
new file mode 100644
index 000000000..b0d55183a
--- /dev/null
+++ b/crypto/src/crypto/tls/ProtocolVersion.cs
@@ -0,0 +1,159 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public sealed class ProtocolVersion
+ {
+ public static readonly ProtocolVersion SSLv3 = new ProtocolVersion(0x0300, "SSL 3.0");
+ public static readonly ProtocolVersion TLSv10 = new ProtocolVersion(0x0301, "TLS 1.0");
+ public static readonly ProtocolVersion TLSv11 = new ProtocolVersion(0x0302, "TLS 1.1");
+ public static readonly ProtocolVersion TLSv12 = new ProtocolVersion(0x0303, "TLS 1.2");
+ public static readonly ProtocolVersion DTLSv10 = new ProtocolVersion(0xFEFF, "DTLS 1.0");
+ public static readonly ProtocolVersion DTLSv12 = new ProtocolVersion(0xFEFD, "DTLS 1.2");
+
+ private readonly int version;
+ private readonly String name;
+
+ private ProtocolVersion(int v, String name)
+ {
+ this.version = v & 0xffff;
+ this.name = name;
+ }
+
+ public int FullVersion
+ {
+ get { return version; }
+ }
+
+ public int MajorVersion
+ {
+ get { return version >> 8; }
+ }
+
+ public int MinorVersion
+ {
+ get { return version & 0xff; }
+ }
+
+ public bool IsDtls
+ {
+ get { return MajorVersion == 0xFE; }
+ }
+
+ public bool IsSsl
+ {
+ get { return this == SSLv3; }
+ }
+
+ public bool IsTls
+ {
+ get { return MajorVersion == 0x03; }
+ }
+
+ public ProtocolVersion GetEquivalentTLSVersion()
+ {
+ if (!IsDtls)
+ {
+ return this;
+ }
+ if (this == DTLSv10)
+ {
+ return TLSv11;
+ }
+ return TLSv12;
+ }
+
+ public bool IsEqualOrEarlierVersionOf(ProtocolVersion version)
+ {
+ if (MajorVersion != version.MajorVersion)
+ {
+ return false;
+ }
+ int diffMinorVersion = version.MinorVersion - MinorVersion;
+ return IsDtls ? diffMinorVersion <= 0 : diffMinorVersion >= 0;
+ }
+
+ public bool IsLaterVersionOf(ProtocolVersion version)
+ {
+ if (MajorVersion != version.MajorVersion)
+ {
+ return false;
+ }
+ int diffMinorVersion = version.MinorVersion - MinorVersion;
+ return IsDtls ? diffMinorVersion > 0 : diffMinorVersion < 0;
+ }
+
+ public override bool Equals(object other)
+ {
+ return this == other || (other is ProtocolVersion && Equals((ProtocolVersion)other));
+ }
+
+ public bool Equals(ProtocolVersion other)
+ {
+ return other != null && this.version == other.version;
+ }
+
+ public override int GetHashCode()
+ {
+ return version;
+ }
+
+ /// <exception cref="IOException"/>
+ public static ProtocolVersion Get(int major, int minor)
+ {
+ switch (major)
+ {
+ case 0x03:
+ {
+ switch (minor)
+ {
+ case 0x00:
+ return SSLv3;
+ case 0x01:
+ return TLSv10;
+ case 0x02:
+ return TLSv11;
+ case 0x03:
+ return TLSv12;
+ }
+ return GetUnknownVersion(major, minor, "TLS");
+ }
+ case 0xFE:
+ {
+ switch (minor)
+ {
+ case 0xFF:
+ return DTLSv10;
+ case 0xFE:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ case 0xFD:
+ return DTLSv12;
+ }
+ return GetUnknownVersion(major, minor, "DTLS");
+ }
+ default:
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public override string ToString()
+ {
+ return name;
+ }
+
+ private static ProtocolVersion GetUnknownVersion(int major, int minor, string prefix)
+ {
+ TlsUtilities.CheckUint8(major);
+ TlsUtilities.CheckUint8(minor);
+
+ int v = (major << 8) | minor;
+ String hex = Platform.ToUpperInvariant(Convert.ToString(0x10000 | v, 16).Substring(1));
+ return new ProtocolVersion(v, prefix + " 0x" + hex);
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs
index 9db7d7d90..6011daada 100644
--- a/crypto/src/crypto/tls/PskTlsClient.cs
+++ b/crypto/src/crypto/tls/PskTlsClient.cs
@@ -3,168 +3,168 @@ using System.Collections;
namespace Org.BouncyCastle.Crypto.Tls
{
- public abstract class PskTlsClient
- :TlsClient
- {
- protected TlsCipherFactory cipherFactory;
- protected TlsPskIdentity pskIdentity;
+ public abstract class PskTlsClient
+ :TlsClient
+ {
+ protected TlsCipherFactory cipherFactory;
+ protected TlsPskIdentity pskIdentity;
protected TlsClientContext context;
- protected CompressionMethod selectedCompressionMethod;
- protected CipherSuite selectedCipherSuite;
+ protected byte selectedCompressionMethod;
+ protected int selectedCipherSuite;
public PskTlsClient(TlsPskIdentity pskIdentity)
- : this(new DefaultTlsCipherFactory(), pskIdentity)
- {
- }
+ : this(new DefaultTlsCipherFactory(), pskIdentity)
+ {
+ }
public PskTlsClient(TlsCipherFactory cipherFactory, TlsPskIdentity pskIdentity)
- {
- this.cipherFactory = cipherFactory;
- this.pskIdentity = pskIdentity;
- }
+ {
+ this.cipherFactory = cipherFactory;
+ this.pskIdentity = pskIdentity;
+ }
public virtual void Init(TlsClientContext context)
- {
- this.context = context;
- }
-
- public virtual CipherSuite[] GetCipherSuites()
- {
- return new CipherSuite[] {
- CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
- CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA,
- CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
- CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA,
- CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA,
- CipherSuite.TLS_PSK_WITH_RC4_128_SHA,
- };
- }
+ {
+ this.context = context;
+ }
+
+ public virtual int[] GetCipherSuites()
+ {
+ return new int[] {
+ CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA,
+ CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA,
+ CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_PSK_WITH_RC4_128_SHA,
+ };
+ }
public virtual IDictionary GetClientExtensions()
- {
- return null;
- }
+ {
+ return null;
+ }
- public virtual CompressionMethod[] GetCompressionMethods()
- {
- return new CompressionMethod[] { CompressionMethod.NULL };
- }
+ public virtual byte[] GetCompressionMethods()
+ {
+ return new byte[] { CompressionMethod.NULL };
+ }
public virtual void NotifySessionID(byte[] sessionID)
- {
- // Currently ignored
- }
+ {
+ // Currently ignored
+ }
- public virtual void NotifySelectedCipherSuite(CipherSuite selectedCipherSuite)
- {
- this.selectedCipherSuite = selectedCipherSuite;
- }
+ public virtual void NotifySelectedCipherSuite(int selectedCipherSuite)
+ {
+ this.selectedCipherSuite = selectedCipherSuite;
+ }
- public virtual void NotifySelectedCompressionMethod(CompressionMethod selectedCompressionMethod)
- {
- this.selectedCompressionMethod = selectedCompressionMethod;
- }
+ public virtual void NotifySelectedCompressionMethod(byte selectedCompressionMethod)
+ {
+ this.selectedCompressionMethod = selectedCompressionMethod;
+ }
public virtual void NotifySecureRenegotiation(bool secureRenegotiation)
- {
- if (!secureRenegotiation)
- {
- /*
- * RFC 5746 3.4. If the extension is not present, the server does not support
- * secure renegotiation; set secure_renegotiation flag to FALSE. In this case,
- * some clients may want to terminate the handshake instead of continuing; see
- * Section 4.1 for discussion.
- */
+ {
+ if (!secureRenegotiation)
+ {
+ /*
+ * RFC 5746 3.4. If the extension is not present, the server does not support
+ * secure renegotiation; set secure_renegotiation flag to FALSE. In this case,
+ * some clients may want to terminate the handshake instead of continuing; see
+ * Section 4.1 for discussion.
+ */
// throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
+ }
+ }
public virtual void ProcessServerExtensions(IDictionary serverExtensions)
- {
- }
+ {
+ }
public virtual TlsKeyExchange GetKeyExchange()
- {
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
- return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK);
+ return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK);
case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK);
case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK);
default:
- /*
- * Note: internal error here; the TlsProtocolHandler verifies that the
- * server-selected cipher suite was in the list of client-offered cipher
- * suites, so if we now can't produce an implementation, we shouldn't have
- * offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
public abstract TlsAuthentication GetAuthentication();
public virtual TlsCompression GetCompression()
- {
- switch (selectedCompressionMethod)
- {
- case CompressionMethod.NULL:
- return new TlsNullCompression();
+ {
+ switch (selectedCompressionMethod)
+ {
+ case CompressionMethod.NULL:
+ return new TlsNullCompression();
default:
- /*
- * Note: internal error here; the TlsProtocolHandler verifies that the
- * server-selected compression method was in the list of client-offered compression
- * methods, so if we now can't produce an implementation, we shouldn't have
- * offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected compression method was in the list of client-offered compression
+ * methods, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
public virtual TlsCipher GetCipher()
- {
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
- return cipherFactory.CreateCipher(context, EncryptionAlgorithm.cls_3DES_EDE_CBC,
- DigestAlgorithm.SHA);
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ return cipherFactory.CreateCipher(context, EncryptionAlgorithm.cls_3DES_EDE_CBC,
+ DigestAlgorithm.SHA);
case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
- return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_128_CBC,
- DigestAlgorithm.SHA);
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_128_CBC,
+ DigestAlgorithm.SHA);
case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
- return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_256_CBC,
- DigestAlgorithm.SHA);
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_256_CBC,
+ DigestAlgorithm.SHA);
case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
@@ -173,19 +173,19 @@ namespace Org.BouncyCastle.Crypto.Tls
DigestAlgorithm.SHA);
default:
- /*
- * Note: internal error here; the TlsProtocolHandler verifies that the
- * server-selected cipher suite was in the list of client-offered cipher
- * suites, so if we now can't produce an implementation, we shouldn't have
- * offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected virtual TlsKeyExchange CreatePskKeyExchange(KeyExchangeAlgorithm keyExchange)
- {
- return new TlsPskKeyExchange(context, keyExchange, pskIdentity);
- }
- }
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
+ {
+ return new TlsPskKeyExchange(context, keyExchange, pskIdentity);
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/RecordStream.cs b/crypto/src/crypto/tls/RecordStream.cs
index 4a5cdc1c9..ce8882cbe 100644
--- a/crypto/src/crypto/tls/RecordStream.cs
+++ b/crypto/src/crypto/tls/RecordStream.cs
@@ -45,21 +45,21 @@ namespace Org.BouncyCastle.Crypto.Tls
public void ReadData()
{
- ContentType type = (ContentType)TlsUtilities.ReadUint8(inStr);
+ byte contentType = TlsUtilities.ReadUint8(inStr);
TlsUtilities.CheckVersion(inStr);
int size = TlsUtilities.ReadUint16(inStr);
- byte[] buf = DecodeAndVerify(type, inStr, size);
- handler.ProcessData(type, buf, 0, buf.Length);
+ byte[] buf = DecodeAndVerify(contentType, inStr, size);
+ handler.ProcessData(contentType, buf, 0, buf.Length);
}
internal byte[] DecodeAndVerify(
- ContentType type,
+ byte contentType,
Stream inStr,
int len)
{
byte[] buf = new byte[len];
TlsUtilities.ReadFully(buf, inStr);
- byte[] decoded = readCipher.DecodeCiphertext(type, buf, 0, buf.Length);
+ byte[] decoded = readCipher.DecodeCiphertext(contentType, buf, 0, buf.Length);
Stream cOut = readCompression.Decompress(buffer);
@@ -76,10 +76,10 @@ namespace Org.BouncyCastle.Crypto.Tls
}
internal void WriteMessage(
- ContentType type,
- byte[] message,
- int offset,
- int len)
+ byte type,
+ byte[] message,
+ int offset,
+ int len)
{
if (type == ContentType.handshake)
{
diff --git a/crypto/src/crypto/tls/SignatureAlgorithm.cs b/crypto/src/crypto/tls/SignatureAlgorithm.cs
new file mode 100644
index 000000000..35b961762
--- /dev/null
+++ b/crypto/src/crypto/tls/SignatureAlgorithm.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ /**
+ * RFC 5246 7.4.1.4.1 (in RFC 2246, there were no specific values assigned)
+ */
+ public abstract class SignatureAlgorithm
+ {
+ public const byte anonymous = 0;
+ public const byte rsa = 1;
+ public const byte dsa = 2;
+ public const byte ecdsa = 3;
+ }
+}
diff --git a/crypto/src/crypto/tls/SignatureAndHashAlgorithm.cs b/crypto/src/crypto/tls/SignatureAndHashAlgorithm.cs
new file mode 100644
index 000000000..f74205b62
--- /dev/null
+++ b/crypto/src/crypto/tls/SignatureAndHashAlgorithm.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ /**
+ * RFC 5246 7.4.1.4.1
+ */
+ public class SignatureAndHashAlgorithm
+ {
+ protected readonly byte mHash;
+ protected readonly byte mSignature;
+
+ /**
+ * @param hash {@link HashAlgorithm}
+ * @param signature {@link SignatureAlgorithm}
+ */
+ public SignatureAndHashAlgorithm(byte hash, byte signature)
+ {
+ if (!TlsUtilities.IsValidUint8(hash))
+ {
+ throw new ArgumentException("should be a uint8", "hash");
+ }
+ if (!TlsUtilities.IsValidUint8(signature))
+ {
+ throw new ArgumentException("should be a uint8", "signature");
+ }
+ if (signature == SignatureAlgorithm.anonymous)
+ {
+ throw new ArgumentException("MUST NOT be \"anonymous\"", "signature");
+ }
+
+ this.mHash = hash;
+ this.mSignature = signature;
+ }
+
+ /**
+ * @return {@link HashAlgorithm}
+ */
+ public virtual byte Hash
+ {
+ get { return mHash; }
+ }
+
+ /**
+ * @return {@link SignatureAlgorithm}
+ */
+ public virtual byte Signature
+ {
+ get { return mSignature; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is SignatureAndHashAlgorithm))
+ {
+ return false;
+ }
+ SignatureAndHashAlgorithm other = (SignatureAndHashAlgorithm)obj;
+ return other.Hash == Hash && other.Signature == Signature;
+ }
+
+ public override int GetHashCode()
+ {
+ return ((int)Hash << 16) | (int)Signature;
+ }
+
+ /**
+ * Encode this {@link SignatureAndHashAlgorithm} to a {@link Stream}.
+ *
+ * @param output the {@link Stream} to encode to.
+ * @throws IOException
+ */
+ public virtual void Encode(Stream output)
+ {
+ TlsUtilities.WriteUint8(Hash, output);
+ TlsUtilities.WriteUint8(Signature, output);
+ }
+
+ /**
+ * Parse a {@link SignatureAndHashAlgorithm} from a {@link Stream}.
+ *
+ * @param input the {@link Stream} to parse from.
+ * @return a {@link SignatureAndHashAlgorithm} object.
+ * @throws IOException
+ */
+ public static SignatureAndHashAlgorithm Parse(Stream input)
+ {
+ byte hash = TlsUtilities.ReadUint8(input);
+ byte signature = TlsUtilities.ReadUint8(input);
+ return new SignatureAndHashAlgorithm(hash, signature);
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/SrpTlsClient.cs b/crypto/src/crypto/tls/SrpTlsClient.cs
index 6c2638bb3..f9c8ccc74 100644
--- a/crypto/src/crypto/tls/SrpTlsClient.cs
+++ b/crypto/src/crypto/tls/SrpTlsClient.cs
@@ -6,183 +6,183 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls
{
- public abstract class SrpTlsClient
- : TlsClient
- {
- protected TlsCipherFactory cipherFactory;
- protected byte[] identity;
- protected byte[] password;
-
- protected TlsClientContext context;
-
- protected CompressionMethod selectedCompressionMethod;
- protected CipherSuite selectedCipherSuite;
-
- public SrpTlsClient(byte[] identity, byte[] password)
- : this(new DefaultTlsCipherFactory(), identity, password)
- {
- }
-
- public SrpTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password)
- {
- this.cipherFactory = cipherFactory;
- this.identity = Arrays.Clone(identity);
- this.password = Arrays.Clone(password);
- }
-
- public virtual void Init(TlsClientContext context)
- {
- this.context = context;
- }
-
- public virtual CipherSuite[] GetCipherSuites()
- {
- return new CipherSuite[] {
- CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
- };
- }
-
- public virtual IDictionary GetClientExtensions()
- {
- IDictionary clientExtensions = Platform.CreateHashtable();
-
- MemoryStream srpData = new MemoryStream();
- TlsUtilities.WriteOpaque8(this.identity, srpData);
- clientExtensions[ExtensionType.srp] = srpData.ToArray();
-
- return clientExtensions;
- }
-
- public virtual CompressionMethod[] GetCompressionMethods()
- {
- return new CompressionMethod[] { CompressionMethod.NULL };
- }
-
- public virtual void NotifySessionID(byte[] sessionID)
- {
- // Currently ignored
- }
-
- public virtual void NotifySelectedCipherSuite(CipherSuite selectedCipherSuite)
- {
- this.selectedCipherSuite = selectedCipherSuite;
- }
-
- public virtual void NotifySelectedCompressionMethod(CompressionMethod selectedCompressionMethod)
- {
+ public abstract class SrpTlsClient
+ : TlsClient
+ {
+ protected TlsCipherFactory cipherFactory;
+ protected byte[] identity;
+ protected byte[] password;
+
+ protected TlsClientContext context;
+
+ protected byte selectedCompressionMethod;
+ protected int selectedCipherSuite;
+
+ public SrpTlsClient(byte[] identity, byte[] password)
+ : this(new DefaultTlsCipherFactory(), identity, password)
+ {
+ }
+
+ public SrpTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password)
+ {
+ this.cipherFactory = cipherFactory;
+ this.identity = Arrays.Clone(identity);
+ this.password = Arrays.Clone(password);
+ }
+
+ public virtual void Init(TlsClientContext context)
+ {
+ this.context = context;
+ }
+
+ public virtual int[] GetCipherSuites()
+ {
+ return new int[] {
+ CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ };
+ }
+
+ public virtual IDictionary GetClientExtensions()
+ {
+ IDictionary clientExtensions = Platform.CreateHashtable();
+
+ MemoryStream srpData = new MemoryStream();
+ TlsUtilities.WriteOpaque8(this.identity, srpData);
+ clientExtensions[ExtensionType.srp] = srpData.ToArray();
+
+ return clientExtensions;
+ }
+
+ public virtual byte[] GetCompressionMethods()
+ {
+ return new byte[] { CompressionMethod.NULL };
+ }
+
+ public virtual void NotifySessionID(byte[] sessionID)
+ {
+ // Currently ignored
+ }
+
+ public virtual void NotifySelectedCipherSuite(int selectedCipherSuite)
+ {
+ this.selectedCipherSuite = selectedCipherSuite;
+ }
+
+ public virtual void NotifySelectedCompressionMethod(byte selectedCompressionMethod)
+ {
this.selectedCompressionMethod = selectedCompressionMethod;
}
- public virtual void NotifySecureRenegotiation(bool secureRenegotiation)
- {
- if (!secureRenegotiation)
- {
- /*
- * RFC 5746 3.4. If the extension is not present, the server does not support
- * secure renegotiation; set secure_renegotiation flag to FALSE. In this case,
- * some clients may want to terminate the handshake instead of continuing; see
- * Section 4.1 for discussion.
- */
+ public virtual void NotifySecureRenegotiation(bool secureRenegotiation)
+ {
+ if (!secureRenegotiation)
+ {
+ /*
+ * RFC 5746 3.4. If the extension is not present, the server does not support
+ * secure renegotiation; set secure_renegotiation flag to FALSE. In this case,
+ * some clients may want to terminate the handshake instead of continuing; see
+ * Section 4.1 for discussion.
+ */
// throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
-
- public virtual void ProcessServerExtensions(IDictionary serverExtensions)
- {
- // There is no server response for the SRP extension
- }
-
- public virtual TlsKeyExchange GetKeyExchange()
- {
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
- return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP);
-
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
- return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_RSA);
-
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
- return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_DSS);
-
- default:
- /*
- * Note: internal error here; the TlsProtocolHandler verifies that the
- * server-selected cipher suite was in the list of client-offered cipher
- * suites, so if we now can't produce an implementation, we shouldn't have
- * offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public abstract TlsAuthentication GetAuthentication();
-
- public virtual TlsCompression GetCompression()
- {
- switch (selectedCompressionMethod)
- {
- case CompressionMethod.NULL:
- return new TlsNullCompression();
-
- default:
- /*
- * Note: internal error here; the TlsProtocolHandler verifies that the
- * server-selected compression method was in the list of client-offered compression
- * methods, so if we now can't produce an implementation, we shouldn't have
- * offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public virtual TlsCipher GetCipher()
- {
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
- return cipherFactory.CreateCipher(context, EncryptionAlgorithm.cls_3DES_EDE_CBC, DigestAlgorithm.SHA);
-
- case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
- return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_128_CBC, DigestAlgorithm.SHA);
-
- case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
- return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_256_CBC, DigestAlgorithm.SHA);
-
- default:
- /*
- * Note: internal error here; the TlsProtocolHandler verifies that the
- * server-selected cipher suite was in the list of client-offered cipher
- * suites, so if we now can't produce an implementation, we shouldn't have
- * offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected virtual TlsKeyExchange CreateSrpKeyExchange(KeyExchangeAlgorithm keyExchange)
- {
- return new TlsSrpKeyExchange(context, keyExchange, identity, password);
- }
- }
+ }
+ }
+
+ public virtual void ProcessServerExtensions(IDictionary serverExtensions)
+ {
+ // There is no server response for the SRP extension
+ }
+
+ public virtual TlsKeyExchange GetKeyExchange()
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+ return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP);
+
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+ return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_RSA);
+
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+ return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_DSS);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public abstract TlsAuthentication GetAuthentication();
+
+ public virtual TlsCompression GetCompression()
+ {
+ switch (selectedCompressionMethod)
+ {
+ case CompressionMethod.NULL:
+ return new TlsNullCompression();
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected compression method was in the list of client-offered compression
+ * methods, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public virtual TlsCipher GetCipher()
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+ return cipherFactory.CreateCipher(context, EncryptionAlgorithm.cls_3DES_EDE_CBC, DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+ return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_128_CBC, DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+ return cipherFactory.CreateCipher(context, EncryptionAlgorithm.AES_256_CBC, DigestAlgorithm.SHA);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange)
+ {
+ return new TlsSrpKeyExchange(context, keyExchange, identity, password);
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsBlockCipher.cs b/crypto/src/crypto/tls/TlsBlockCipher.cs
index d77f118f4..cfbceb25e 100644
--- a/crypto/src/crypto/tls/TlsBlockCipher.cs
+++ b/crypto/src/crypto/tls/TlsBlockCipher.cs
@@ -9,13 +9,13 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// A generic TLS 1.0 block cipher. This can be used for AES or 3DES for example.
- /// </summary>
- public class TlsBlockCipher
+ /// <summary>
+ /// A generic TLS 1.0 block cipher. This can be used for AES or 3DES for example.
+ /// </summary>
+ public class TlsBlockCipher
: TlsCipher
- {
- protected TlsClientContext context;
+ {
+ protected TlsClientContext context;
protected byte[] randomData;
protected IBlockCipher encryptCipher;
@@ -25,86 +25,86 @@ namespace Org.BouncyCastle.Crypto.Tls
protected TlsMac rMac;
public virtual TlsMac WriteMac
- {
+ {
get { return wMac; }
- }
+ }
- public virtual TlsMac ReadMac
- {
+ public virtual TlsMac ReadMac
+ {
get { return rMac; }
- }
+ }
- public TlsBlockCipher(TlsClientContext context, IBlockCipher encryptCipher,
- IBlockCipher decryptCipher, IDigest writeDigest, IDigest readDigest, int cipherKeySize)
- {
- this.context = context;
+ public TlsBlockCipher(TlsClientContext context, IBlockCipher encryptCipher,
+ IBlockCipher decryptCipher, IDigest writeDigest, IDigest readDigest, int cipherKeySize)
+ {
+ this.context = context;
this.randomData = new byte[256];
context.SecureRandom.NextBytes(randomData);
this.encryptCipher = encryptCipher;
- this.decryptCipher = decryptCipher;
+ this.decryptCipher = decryptCipher;
- int prfSize = (2 * cipherKeySize) + writeDigest.GetDigestSize()
- + readDigest.GetDigestSize() + encryptCipher.GetBlockSize()
- + decryptCipher.GetBlockSize();
+ int prfSize = (2 * cipherKeySize) + writeDigest.GetDigestSize()
+ + readDigest.GetDigestSize() + encryptCipher.GetBlockSize()
+ + decryptCipher.GetBlockSize();
- SecurityParameters securityParameters = context.SecurityParameters;
+ SecurityParameters securityParameters = context.SecurityParameters;
- byte[] keyBlock = TlsUtilities.PRF(securityParameters.masterSecret, "key expansion",
- TlsUtilities.Concat(securityParameters.serverRandom, securityParameters.clientRandom),
- prfSize);
+ byte[] keyBlock = TlsUtilities.PRF(securityParameters.masterSecret, "key expansion",
+ TlsUtilities.Concat(securityParameters.serverRandom, securityParameters.clientRandom),
+ prfSize);
- int offset = 0;
+ int offset = 0;
- // Init MACs
- wMac = CreateTlsMac(writeDigest, keyBlock, ref offset);
+ // Init MACs
+ wMac = CreateTlsMac(writeDigest, keyBlock, ref offset);
rMac = CreateTlsMac(readDigest, keyBlock, ref offset);
- // Build keys
- KeyParameter encryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize);
- KeyParameter decryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize);
+ // Build keys
+ KeyParameter encryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize);
+ KeyParameter decryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize);
- // Add IVs
- ParametersWithIV encryptParams = CreateParametersWithIV(encryptKey,
- keyBlock, ref offset, encryptCipher.GetBlockSize());
- ParametersWithIV decryptParams = CreateParametersWithIV(decryptKey,
- keyBlock, ref offset, decryptCipher.GetBlockSize());
+ // Add IVs
+ ParametersWithIV encryptParams = CreateParametersWithIV(encryptKey,
+ keyBlock, ref offset, encryptCipher.GetBlockSize());
+ ParametersWithIV decryptParams = CreateParametersWithIV(decryptKey,
+ keyBlock, ref offset, decryptCipher.GetBlockSize());
- if (offset != prfSize)
- throw new TlsFatalAlert(AlertDescription.internal_error);
+ if (offset != prfSize)
+ throw new TlsFatalAlert(AlertDescription.internal_error);
- // Init Ciphers
- encryptCipher.Init(true, encryptParams);
- decryptCipher.Init(false, decryptParams);
- }
+ // Init Ciphers
+ encryptCipher.Init(true, encryptParams);
+ decryptCipher.Init(false, decryptParams);
+ }
protected virtual TlsMac CreateTlsMac(IDigest digest, byte[] buf, ref int off)
- {
- int len = digest.GetDigestSize();
- TlsMac mac = new TlsMac(digest, buf, off, len);
- off += len;
- return mac;
- }
+ {
+ int len = digest.GetDigestSize();
+ TlsMac mac = new TlsMac(digest, buf, off, len);
+ off += len;
+ return mac;
+ }
protected virtual KeyParameter CreateKeyParameter(byte[] buf, ref int off, int len)
- {
- KeyParameter key = new KeyParameter(buf, off, len);
- off += len;
- return key;
- }
+ {
+ KeyParameter key = new KeyParameter(buf, off, len);
+ off += len;
+ return key;
+ }
protected virtual ParametersWithIV CreateParametersWithIV(KeyParameter key,
- byte[] buf, ref int off, int len)
- {
- ParametersWithIV ivParams = new ParametersWithIV(key, buf, off, len);
- off += len;
- return ivParams;
- }
-
- public virtual byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len)
- {
- int blocksize = encryptCipher.GetBlockSize();
+ byte[] buf, ref int off, int len)
+ {
+ ParametersWithIV ivParams = new ParametersWithIV(key, buf, off, len);
+ off += len;
+ return ivParams;
+ }
+
+ public virtual byte[] EncodePlaintext(byte type, byte[] plaintext, int offset, int len)
+ {
+ int blocksize = encryptCipher.GetBlockSize();
int padding_length = blocksize - 1 - ((len + wMac.Size) % blocksize);
//bool isTls = context.ServerVersion.FullVersion >= ProtocolVersion.TLSv10.FullVersion;
@@ -119,24 +119,24 @@ namespace Org.BouncyCastle.Crypto.Tls
}
int totalsize = len + wMac.Size + padding_length + 1;
- byte[] outbuf = new byte[totalsize];
- Array.Copy(plaintext, offset, outbuf, 0, len);
+ byte[] outbuf = new byte[totalsize];
+ Array.Copy(plaintext, offset, outbuf, 0, len);
byte[] mac = wMac.CalculateMac(type, plaintext, offset, len);
- Array.Copy(mac, 0, outbuf, len, mac.Length);
- int paddoffset = len + mac.Length;
+ Array.Copy(mac, 0, outbuf, len, mac.Length);
+ int paddoffset = len + mac.Length;
for (int i = 0; i <= padding_length; i++)
- {
+ {
outbuf[i + paddoffset] = (byte)padding_length;
- }
- for (int i = 0; i < totalsize; i += blocksize)
- {
- encryptCipher.ProcessBlock(outbuf, i, outbuf, i);
- }
- return outbuf;
- }
-
- public virtual byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len)
- {
+ }
+ for (int i = 0; i < totalsize; i += blocksize)
+ {
+ encryptCipher.ProcessBlock(outbuf, i, outbuf, i);
+ }
+ return outbuf;
+ }
+
+ public virtual byte[] DecodeCiphertext(byte type, byte[] ciphertext, int offset, int len)
+ {
int blockSize = decryptCipher.GetBlockSize();
int macSize = rMac.Size;
@@ -173,7 +173,7 @@ namespace Org.BouncyCastle.Crypto.Tls
throw new TlsFatalAlert(AlertDescription.bad_record_mac);
return Arrays.Copy(ciphertext, offset, macInputLen);
- }
+ }
protected virtual int CheckPaddingConstantTime(byte[] buf, int off, int len, int blockSize, int macSize)
{
@@ -224,28 +224,28 @@ namespace Org.BouncyCastle.Crypto.Tls
}
protected virtual int ChooseExtraPadBlocks(SecureRandom r, int max)
- {
+ {
// return r.NextInt(max + 1);
- uint x = (uint)r.NextInt();
- int n = LowestBitSet(x);
- return System.Math.Min(n, max);
- }
+ uint x = (uint)r.NextInt();
+ int n = LowestBitSet(x);
+ return System.Math.Min(n, max);
+ }
private int LowestBitSet(uint x)
- {
- if (x == 0)
- {
- return 32;
- }
-
- int n = 0;
- while ((x & 1) == 0)
- {
- ++n;
- x >>= 1;
- }
- return n;
- }
- }
+ {
+ if (x == 0)
+ {
+ return 32;
+ }
+
+ int n = 0;
+ while ((x & 1) == 0)
+ {
+ ++n;
+ x >>= 1;
+ }
+ return n;
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsCipher.cs b/crypto/src/crypto/tls/TlsCipher.cs
index 22c769d82..a58f4943f 100644
--- a/crypto/src/crypto/tls/TlsCipher.cs
+++ b/crypto/src/crypto/tls/TlsCipher.cs
@@ -3,12 +3,12 @@ using System.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
- public interface TlsCipher
- {
- /// <exception cref="IOException"></exception>
- byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len);
+ public interface TlsCipher
+ {
+ /// <exception cref="IOException"></exception>
+ byte[] EncodePlaintext(byte type, byte[] plaintext, int offset, int len);
- /// <exception cref="IOException"></exception>
- byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len);
- }
+ /// <exception cref="IOException"></exception>
+ byte[] DecodeCiphertext(byte type, byte[] ciphertext, int offset, int len);
+ }
}
diff --git a/crypto/src/crypto/tls/TlsCipherFactory.cs b/crypto/src/crypto/tls/TlsCipherFactory.cs
index 0756603f4..bd65f8b4b 100644
--- a/crypto/src/crypto/tls/TlsCipherFactory.cs
+++ b/crypto/src/crypto/tls/TlsCipherFactory.cs
@@ -3,10 +3,10 @@ using System.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
- public interface TlsCipherFactory
- {
- /// <exception cref="IOException"></exception>
- TlsCipher CreateCipher(TlsClientContext context, EncryptionAlgorithm encryptionAlgorithm,
- DigestAlgorithm digestAlgorithm);
- }
+ public interface TlsCipherFactory
+ {
+ /// <exception cref="IOException"></exception>
+ TlsCipher CreateCipher(TlsClientContext context, int encryptionAlgorithm,
+ DigestAlgorithm digestAlgorithm);
+ }
}
diff --git a/crypto/src/crypto/tls/TlsClient.cs b/crypto/src/crypto/tls/TlsClient.cs
index eceaa3cd3..9e7937c94 100644
--- a/crypto/src/crypto/tls/TlsClient.cs
+++ b/crypto/src/crypto/tls/TlsClient.cs
@@ -4,60 +4,60 @@ using System.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
- public interface TlsClient
- {
- /// <summary>
- /// Called at the start of a new TLS session, before any other methods.
- /// </summary>
- /// <param name="context">
- /// A <see cref="TlsProtocolHandler"/>
- /// </param>
- void Init(TlsClientContext context);
+ public interface TlsClient
+ {
+ /// <summary>
+ /// Called at the start of a new TLS session, before any other methods.
+ /// </summary>
+ /// <param name="context">
+ /// A <see cref="TlsProtocolHandler"/>
+ /// </param>
+ void Init(TlsClientContext context);
- /// <summary>
- /// Get the list of cipher suites that this client supports.
- /// </summary>
- /// <returns>
- /// An array of <see cref="CipherSuite"/>, each specifying a supported cipher suite.
- /// </returns>
- CipherSuite[] GetCipherSuites();
+ /// <summary>
+ /// Get the list of cipher suites that this client supports.
+ /// </summary>
+ /// <returns>
+ /// An array of <see cref="CipherSuite"/> values, each specifying a supported cipher suite.
+ /// </returns>
+ int[] GetCipherSuites();
/// <summary>
/// Get the list of compression methods that this client supports.
/// </summary>
/// <returns>
- /// An array of <see cref="CompressionMethod"/>, each specifying a supported compression method.
+ /// An array of <see cref="CompressionMethod"/> values, each specifying a supported compression method.
/// </returns>
- CompressionMethod[] GetCompressionMethods();
+ byte[] GetCompressionMethods();
- /// <summary>
- /// Get the (optional) table of client extensions to be included in (extended) client hello.
- /// </summary>
- /// <returns>
- /// A <see cref="IDictionary"/> (<see cref="ExtensionType"/> -> byte[]). May be null.
- /// </returns>
- /// <exception cref="IOException"></exception>
- IDictionary GetClientExtensions();
+ /// <summary>
+ /// Get the (optional) table of client extensions to be included in (extended) client hello.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="IDictionary"/> (Int32 -> byte[]). May be null.
+ /// </returns>
+ /// <exception cref="IOException"></exception>
+ IDictionary GetClientExtensions();
- /// <summary>
- /// Reports the session ID once it has been determined.
- /// </summary>
- /// <param name="sessionID">
- /// A <see cref="System.Byte"/>
- /// </param>
- void NotifySessionID(byte[] sessionID);
+ /// <summary>
+ /// Reports the session ID once it has been determined.
+ /// </summary>
+ /// <param name="sessionID">
+ /// A <see cref="System.Byte"/>
+ /// </param>
+ void NotifySessionID(byte[] sessionID);
- /// <summary>
- /// Report the cipher suite that was selected by the server.
- /// </summary>
- /// <remarks>
- /// The protocol handler validates this value against the offered cipher suites
- /// <seealso cref="GetCipherSuites"/>
- /// </remarks>
- /// <param name="selectedCipherSuite">
- /// A <see cref="CipherSuite"/>
- /// </param>
- void NotifySelectedCipherSuite(CipherSuite selectedCipherSuite);
+ /// <summary>
+ /// Report the cipher suite that was selected by the server.
+ /// </summary>
+ /// <remarks>
+ /// The protocol handler validates this value against the offered cipher suites
+ /// <seealso cref="GetCipherSuites"/>
+ /// </remarks>
+ /// <param name="selectedCipherSuite">
+ /// A <see cref="CipherSuite"/>
+ /// </param>
+ void NotifySelectedCipherSuite(int selectedCipherSuite);
/// <summary>
/// Report the compression method that was selected by the server.
@@ -69,61 +69,61 @@ namespace Org.BouncyCastle.Crypto.Tls
/// <param name="selectedCompressionMethod">
/// A <see cref="CompressionMethod"/>
/// </param>
- void NotifySelectedCompressionMethod(CompressionMethod selectedCompressionMethod);
+ void NotifySelectedCompressionMethod(byte selectedCompressionMethod);
- /// <summary>
- /// Report whether the server supports secure renegotiation
- /// </summary>
- /// <remarks>
- /// The protocol handler automatically processes the relevant extensions
- /// </remarks>
- /// <param name="secureRenegotiation">
- /// A <see cref="System.Boolean"/>, true if the server supports secure renegotiation
- /// </param>
- /// <exception cref="IOException"></exception>
- void NotifySecureRenegotiation(bool secureRenegotiation);
+ /// <summary>
+ /// Report whether the server supports secure renegotiation
+ /// </summary>
+ /// <remarks>
+ /// The protocol handler automatically processes the relevant extensions
+ /// </remarks>
+ /// <param name="secureRenegotiation">
+ /// A <see cref="System.Boolean"/>, true if the server supports secure renegotiation
+ /// </param>
+ /// <exception cref="IOException"></exception>
+ void NotifySecureRenegotiation(bool secureRenegotiation);
- /// <summary>
- /// Report the extensions from an extended server hello.
- /// </summary>
- /// <remarks>
- /// Will only be called if we returned a non-null result from <see cref="GetClientExtensions"/>.
- /// </remarks>
- /// <param name="serverExtensions">
- /// A <see cref="IDictionary"/> (<see cref="ExtensionType"/> -> byte[])
- /// </param>
- void ProcessServerExtensions(IDictionary serverExtensions);
+ /// <summary>
+ /// Report the extensions from an extended server hello.
+ /// </summary>
+ /// <remarks>
+ /// Will only be called if we returned a non-null result from <see cref="GetClientExtensions"/>.
+ /// </remarks>
+ /// <param name="serverExtensions">
+ /// A <see cref="IDictionary"/> (Int32 -> byte[])
+ /// </param>
+ void ProcessServerExtensions(IDictionary serverExtensions);
- /// <summary>
- /// Return an implementation of <see cref="TlsKeyExchange"/> to negotiate the key exchange
- /// part of the protocol.
- /// </summary>
- /// <returns>
- /// A <see cref="TlsKeyExchange"/>
- /// </returns>
- /// <exception cref="IOException"/>
- TlsKeyExchange GetKeyExchange();
+ /// <summary>
+ /// Return an implementation of <see cref="TlsKeyExchange"/> to negotiate the key exchange
+ /// part of the protocol.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="TlsKeyExchange"/>
+ /// </returns>
+ /// <exception cref="IOException"/>
+ TlsKeyExchange GetKeyExchange();
- /// <summary>
- /// Return an implementation of <see cref="TlsAuthentication"/> to handle authentication
- /// part of the protocol.
- /// </summary>
- /// <exception cref="IOException"/>
- TlsAuthentication GetAuthentication();
+ /// <summary>
+ /// Return an implementation of <see cref="TlsAuthentication"/> to handle authentication
+ /// part of the protocol.
+ /// </summary>
+ /// <exception cref="IOException"/>
+ TlsAuthentication GetAuthentication();
- /// <summary>
- /// Return an implementation of <see cref="TlsCompression"/> to handle record compression.
- /// </summary>
- /// <exception cref="IOException"/>
- TlsCompression GetCompression();
+ /// <summary>
+ /// Return an implementation of <see cref="TlsCompression"/> to handle record compression.
+ /// </summary>
+ /// <exception cref="IOException"/>
+ TlsCompression GetCompression();
- /// <summary>
- /// Return an implementation of <see cref="TlsCipher"/> to use for encryption/decryption.
- /// </summary>
- /// <returns>
- /// A <see cref="TlsCipher"/>
- /// </returns>
- /// <exception cref="IOException"/>
- TlsCipher GetCipher();
- }
+ /// <summary>
+ /// Return an implementation of <see cref="TlsCipher"/> to use for encryption/decryption.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="TlsCipher"/>
+ /// </returns>
+ /// <exception cref="IOException"/>
+ TlsCipher GetCipher();
+ }
}
diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
index 40ac416e0..26d76fd3d 100644
--- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
@@ -9,193 +9,193 @@ using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// TLS 1.0 DH key exchange.
- /// </summary>
- internal class TlsDHKeyExchange
- : TlsKeyExchange
- {
- protected TlsClientContext context;
- protected KeyExchangeAlgorithm keyExchange;
- protected TlsSigner tlsSigner;
-
- protected AsymmetricKeyParameter serverPublicKey = null;
- protected DHPublicKeyParameters dhAgreeServerPublicKey = null;
- protected TlsAgreementCredentials agreementCredentials;
- protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null;
-
- internal TlsDHKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange)
- {
- switch (keyExchange)
- {
- case KeyExchangeAlgorithm.DH_RSA:
- case KeyExchangeAlgorithm.DH_DSS:
- this.tlsSigner = null;
- break;
- case KeyExchangeAlgorithm.DHE_RSA:
- this.tlsSigner = new TlsRsaSigner();
- break;
- case KeyExchangeAlgorithm.DHE_DSS:
- this.tlsSigner = new TlsDssSigner();
- break;
- default:
- throw new ArgumentException("unsupported key exchange algorithm", "keyExchange");
- }
-
- this.context = context;
- this.keyExchange = keyExchange;
- }
-
- public virtual void SkipServerCertificate()
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public virtual void ProcessServerCertificate(Certificate serverCertificate)
- {
- X509CertificateStructure x509Cert = serverCertificate.certs[0];
- SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
-
- try
- {
- this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo);
- }
- catch (Exception)
- {
- throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
- }
-
- if (tlsSigner == null)
- {
- try
- {
- this.dhAgreeServerPublicKey = ValidateDHPublicKey((DHPublicKeyParameters)this.serverPublicKey);
- }
- catch (InvalidCastException)
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown);
- }
-
- TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyAgreement);
- }
- else
- {
- if (!tlsSigner.IsValidPublicKey(this.serverPublicKey))
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown);
- }
-
- TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
- }
-
- // TODO
- /*
- * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the
- * signing algorithm for the certificate must be the same as the algorithm for the
- * certificate key."
- */
- }
-
- public virtual void SkipServerKeyExchange()
- {
- // OK
- }
-
- public virtual void ProcessServerKeyExchange(Stream input)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest)
- {
- ClientCertificateType[] types = certificateRequest.CertificateTypes;
- foreach (ClientCertificateType type in types)
- {
- switch (type)
- {
- case ClientCertificateType.rsa_sign:
- case ClientCertificateType.dss_sign:
- case ClientCertificateType.rsa_fixed_dh:
- case ClientCertificateType.dss_fixed_dh:
- case ClientCertificateType.ecdsa_sign:
- break;
- default:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- }
-
- public virtual void SkipClientCredentials()
- {
- this.agreementCredentials = null;
- }
-
- public virtual void ProcessClientCredentials(TlsCredentials clientCredentials)
- {
- if (clientCredentials is TlsAgreementCredentials)
- {
- // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')?
-
- this.agreementCredentials = (TlsAgreementCredentials)clientCredentials;
- }
- else if (clientCredentials is TlsSignerCredentials)
- {
- // OK
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public virtual void GenerateClientKeyExchange(Stream output)
- {
- /*
- * RFC 2246 7.4.7.2 If the client certificate already contains a suitable
- * Diffie-Hellman key, then Yc is implicit and does not need to be sent again. In
- * this case, the Client Key Exchange message will be sent, but will be empty.
- */
- if (agreementCredentials == null)
- {
- GenerateEphemeralClientKeyExchange(dhAgreeServerPublicKey.Parameters, output);
- }
- }
+ /// <summary>
+ /// TLS 1.0 DH key exchange.
+ /// </summary>
+ internal class TlsDHKeyExchange
+ : TlsKeyExchange
+ {
+ protected TlsClientContext context;
+ protected int keyExchange;
+ protected TlsSigner tlsSigner;
+
+ protected AsymmetricKeyParameter serverPublicKey = null;
+ protected DHPublicKeyParameters dhAgreeServerPublicKey = null;
+ protected TlsAgreementCredentials agreementCredentials;
+ protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null;
+
+ internal TlsDHKeyExchange(TlsClientContext context, int keyExchange)
+ {
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.DH_RSA:
+ case KeyExchangeAlgorithm.DH_DSS:
+ this.tlsSigner = null;
+ break;
+ case KeyExchangeAlgorithm.DHE_RSA:
+ this.tlsSigner = new TlsRsaSigner();
+ break;
+ case KeyExchangeAlgorithm.DHE_DSS:
+ this.tlsSigner = new TlsDssSigner();
+ break;
+ default:
+ throw new ArgumentException("unsupported key exchange algorithm", "keyExchange");
+ }
+
+ this.context = context;
+ this.keyExchange = keyExchange;
+ }
+
+ public virtual void SkipServerCertificate()
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public virtual void ProcessServerCertificate(Certificate serverCertificate)
+ {
+ X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
+ SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
+
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo);
+ }
+ catch (Exception)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ if (tlsSigner == null)
+ {
+ try
+ {
+ this.dhAgreeServerPublicKey = ValidateDHPublicKey((DHPublicKeyParameters)this.serverPublicKey);
+ }
+ catch (InvalidCastException)
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyAgreement);
+ }
+ else
+ {
+ if (!tlsSigner.IsValidPublicKey(this.serverPublicKey))
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
+ }
+
+ // TODO
+ /*
+ * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the
+ * signing algorithm for the certificate must be the same as the algorithm for the
+ * certificate key."
+ */
+ }
+
+ public virtual void SkipServerKeyExchange()
+ {
+ // OK
+ }
+
+ public virtual void ProcessServerKeyExchange(Stream input)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest)
+ {
+ byte[] types = certificateRequest.CertificateTypes;
+ foreach (byte type in types)
+ {
+ switch (type)
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.rsa_fixed_dh:
+ case ClientCertificateType.dss_fixed_dh:
+ case ClientCertificateType.ecdsa_sign:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public virtual void SkipClientCredentials()
+ {
+ this.agreementCredentials = null;
+ }
+
+ public virtual void ProcessClientCredentials(TlsCredentials clientCredentials)
+ {
+ if (clientCredentials is TlsAgreementCredentials)
+ {
+ // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')?
+
+ this.agreementCredentials = (TlsAgreementCredentials)clientCredentials;
+ }
+ else if (clientCredentials is TlsSignerCredentials)
+ {
+ // OK
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public virtual void GenerateClientKeyExchange(Stream output)
+ {
+ /*
+ * RFC 2246 7.4.7.2 If the client certificate already contains a suitable
+ * Diffie-Hellman key, then Yc is implicit and does not need to be sent again. In
+ * this case, the Client Key Exchange message will be sent, but will be empty.
+ */
+ if (agreementCredentials == null)
+ {
+ GenerateEphemeralClientKeyExchange(dhAgreeServerPublicKey.Parameters, output);
+ }
+ }
public virtual byte[] GeneratePremasterSecret()
- {
- if (agreementCredentials != null)
- {
- return agreementCredentials.GenerateAgreement(dhAgreeServerPublicKey);
- }
-
- return CalculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
- }
-
- protected virtual bool AreCompatibleParameters(DHParameters a, DHParameters b)
- {
- return a.P.Equals(b.P) && a.G.Equals(b.G);
- }
-
- protected virtual byte[] CalculateDHBasicAgreement(DHPublicKeyParameters publicKey,
- DHPrivateKeyParameters privateKey)
- {
- return TlsDHUtilities.CalculateDHBasicAgreement(publicKey, privateKey);
- }
-
- protected virtual AsymmetricCipherKeyPair GenerateDHKeyPair(DHParameters dhParams)
- {
- return TlsDHUtilities.GenerateDHKeyPair(context.SecureRandom, dhParams);
- }
-
- protected virtual void GenerateEphemeralClientKeyExchange(DHParameters dhParams, Stream output)
- {
- this.dhAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(
- context.SecureRandom, dhParams, output);
- }
-
- protected virtual DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key)
- {
- return TlsDHUtilities.ValidateDHPublicKey(key);
- }
- }
+ {
+ if (agreementCredentials != null)
+ {
+ return agreementCredentials.GenerateAgreement(dhAgreeServerPublicKey);
+ }
+
+ return CalculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
+ }
+
+ protected virtual bool AreCompatibleParameters(DHParameters a, DHParameters b)
+ {
+ return a.P.Equals(b.P) && a.G.Equals(b.G);
+ }
+
+ protected virtual byte[] CalculateDHBasicAgreement(DHPublicKeyParameters publicKey,
+ DHPrivateKeyParameters privateKey)
+ {
+ return TlsDHUtilities.CalculateDHBasicAgreement(publicKey, privateKey);
+ }
+
+ protected virtual AsymmetricCipherKeyPair GenerateDHKeyPair(DHParameters dhParams)
+ {
+ return TlsDHUtilities.GenerateDHKeyPair(context.SecureRandom, dhParams);
+ }
+
+ protected virtual void GenerateEphemeralClientKeyExchange(DHParameters dhParams, Stream output)
+ {
+ this.dhAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(
+ context.SecureRandom, dhParams, output);
+ }
+
+ protected virtual DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key)
+ {
+ return TlsDHUtilities.ValidateDHPublicKey(key);
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
index 725cc1bf3..ee6d6eb44 100644
--- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
@@ -7,50 +7,50 @@ using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Tls
{
- internal class TlsDheKeyExchange
- : TlsDHKeyExchange
- {
- internal TlsDheKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange)
- : base(context, keyExchange)
- {
- }
-
- public override void SkipServerKeyExchange()
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public override void ProcessServerKeyExchange(Stream input)
- {
- SecurityParameters securityParameters = context.SecurityParameters;
-
- ISigner signer = InitSigner(tlsSigner, securityParameters);
- Stream sigIn = new SignerStream(input, signer, null);
-
- byte[] pBytes = TlsUtilities.ReadOpaque16(sigIn);
- byte[] gBytes = TlsUtilities.ReadOpaque16(sigIn);
- byte[] YsBytes = TlsUtilities.ReadOpaque16(sigIn);
-
- byte[] sigByte = TlsUtilities.ReadOpaque16(input);
- if (!signer.VerifySignature(sigByte))
- {
+ internal class TlsDheKeyExchange
+ : TlsDHKeyExchange
+ {
+ internal TlsDheKeyExchange(TlsClientContext context, int keyExchange)
+ : base(context, keyExchange)
+ {
+ }
+
+ public override void SkipServerKeyExchange()
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public override void ProcessServerKeyExchange(Stream input)
+ {
+ SecurityParameters securityParameters = context.SecurityParameters;
+
+ ISigner signer = InitSigner(tlsSigner, securityParameters);
+ Stream sigIn = new SignerStream(input, signer, null);
+
+ byte[] pBytes = TlsUtilities.ReadOpaque16(sigIn);
+ byte[] gBytes = TlsUtilities.ReadOpaque16(sigIn);
+ byte[] YsBytes = TlsUtilities.ReadOpaque16(sigIn);
+
+ byte[] sigByte = TlsUtilities.ReadOpaque16(input);
+ if (!signer.VerifySignature(sigByte))
+ {
throw new TlsFatalAlert(AlertDescription.decrypt_error);
- }
-
- BigInteger p = new BigInteger(1, pBytes);
- BigInteger g = new BigInteger(1, gBytes);
- BigInteger Ys = new BigInteger(1, YsBytes);
-
- this.dhAgreeServerPublicKey = ValidateDHPublicKey(
- new DHPublicKeyParameters(Ys, new DHParameters(p, g)));
- }
-
- protected virtual ISigner InitSigner(TlsSigner tlsSigner, SecurityParameters securityParameters)
- {
- ISigner signer = tlsSigner.CreateVerifyer(this.serverPublicKey);
- signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length);
- signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length);
- return signer;
- }
- }
+ }
+
+ BigInteger p = new BigInteger(1, pBytes);
+ BigInteger g = new BigInteger(1, gBytes);
+ BigInteger Ys = new BigInteger(1, YsBytes);
+
+ this.dhAgreeServerPublicKey = ValidateDHPublicKey(
+ new DHPublicKeyParameters(Ys, new DHParameters(p, g)));
+ }
+
+ protected virtual ISigner InitSigner(TlsSigner tlsSigner, SecurityParameters securityParameters)
+ {
+ ISigner signer = tlsSigner.CreateVerifyer(this.serverPublicKey);
+ signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length);
+ signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length);
+ return signer;
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs
index 36155346a..65d07a10c 100644
--- a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crypto.Tls
: TlsKeyExchange
{
protected TlsClientContext context;
- protected KeyExchangeAlgorithm keyExchange;
+ protected int keyExchange;
protected TlsSigner tlsSigner;
protected AsymmetricKeyParameter serverPublicKey;
@@ -27,7 +27,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected TlsAgreementCredentials agreementCredentials;
protected ECPrivateKeyParameters ecAgreeClientPrivateKey = null;
- internal TlsECDHKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange)
+ internal TlsECDHKeyExchange(TlsClientContext context, int keyExchange)
{
switch (keyExchange)
{
@@ -56,7 +56,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public virtual void ProcessServerCertificate(Certificate serverCertificate)
{
- X509CertificateStructure x509Cert = serverCertificate.certs[0];
+ X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
try
@@ -117,8 +117,8 @@ namespace Org.BouncyCastle.Crypto.Tls
* prohibited because the use of a long-term ECDH client key would jeopardize the
* forward secrecy property of these algorithms.
*/
- ClientCertificateType[] types = certificateRequest.CertificateTypes;
- foreach (ClientCertificateType type in types)
+ byte[] types = certificateRequest.CertificateTypes;
+ foreach (byte type in types)
{
switch (type)
{
diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
index 071d06b91..a671ebfbe 100644
--- a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
@@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Crypto.Tls
*/
internal class TlsECDheKeyExchange : TlsECDHKeyExchange
{
- internal TlsECDheKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange)
+ internal TlsECDheKeyExchange(TlsClientContext context, int keyExchange)
: base(context, keyExchange)
{
}
@@ -30,13 +30,13 @@ namespace Org.BouncyCastle.Crypto.Tls
ISigner signer = InitSigner(tlsSigner, securityParameters);
Stream sigIn = new SignerStream(input, signer, null);
- ECCurveType curveType = (ECCurveType)TlsUtilities.ReadUint8(sigIn);
+ byte curveType = TlsUtilities.ReadUint8(sigIn);
ECDomainParameters curve_params;
// Currently, we only support named curves
if (curveType == ECCurveType.named_curve)
{
- NamedCurve namedCurve = (NamedCurve)TlsUtilities.ReadUint16(sigIn);
+ int namedCurve = TlsUtilities.ReadUint16(sigIn);
// TODO Check namedCurve is one we offered?
@@ -72,8 +72,8 @@ namespace Org.BouncyCastle.Crypto.Tls
* prohibited because the use of a long-term ECDH client key would jeopardize the
* forward secrecy property of these algorithms.
*/
- ClientCertificateType[] types = certificateRequest.CertificateTypes;
- foreach (ClientCertificateType type in types)
+ byte[] types = certificateRequest.CertificateTypes;
+ foreach (byte type in types)
{
switch (type)
{
diff --git a/crypto/src/crypto/tls/TlsException.cs b/crypto/src/crypto/tls/TlsException.cs
deleted file mode 100644
index 59c129105..000000000
--- a/crypto/src/crypto/tls/TlsException.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace Org.BouncyCastle.Crypto.Tls
-{
-#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
- [Serializable]
-#endif
- public class TlsException : Exception
- {
- public TlsException() : base() { }
- public TlsException(string message) : base(message) { }
- public TlsException(string message, Exception exception) : base(message, exception) { }
- }
-}
diff --git a/crypto/src/crypto/tls/TlsFatalAlert.cs b/crypto/src/crypto/tls/TlsFatalAlert.cs
index 0a9cc6f3a..4fb2a41bd 100644
--- a/crypto/src/crypto/tls/TlsFatalAlert.cs
+++ b/crypto/src/crypto/tls/TlsFatalAlert.cs
@@ -3,19 +3,19 @@ using System.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
- public class TlsFatalAlert
- : IOException
- {
- private readonly AlertDescription alertDescription;
+ public class TlsFatalAlert
+ : IOException
+ {
+ private readonly byte alertDescription;
- public TlsFatalAlert(AlertDescription alertDescription)
- {
- this.alertDescription = alertDescription;
- }
+ public TlsFatalAlert(byte alertDescription)
+ {
+ this.alertDescription = alertDescription;
+ }
- public AlertDescription AlertDescription
- {
- get { return alertDescription; }
- }
- }
+ public virtual byte AlertDescription
+ {
+ get { return alertDescription; }
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsMac.cs b/crypto/src/crypto/tls/TlsMac.cs
index 862c887ad..e4313617e 100644
--- a/crypto/src/crypto/tls/TlsMac.cs
+++ b/crypto/src/crypto/tls/TlsMac.cs
@@ -9,103 +9,103 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <remarks>
- /// A generic TLS MAC implementation, which can be used with any kind of
- /// IDigest to act as an HMAC.
- /// </remarks>
- public class TlsMac
- {
- protected long seqNo;
- protected byte[] secret;
- protected HMac mac;
-
- /**
- * Generate a new instance of an TlsMac.
- *
- * @param digest The digest to use.
- * @param key_block A byte-array where the key for this mac is located.
- * @param offset The number of bytes to skip, before the key starts in the buffer.
- * @param len The length of the key.
- */
- public TlsMac(
- IDigest digest,
- byte[] key_block,
- int offset,
- int len)
- {
- this.seqNo = 0;
-
- KeyParameter param = new KeyParameter(key_block, offset, len);
-
- this.secret = Arrays.Clone(param.GetKey());
-
- this.mac = new HMac(digest);
- this.mac.Init(param);
- }
-
- /**
- * @return the MAC write secret
- */
- public virtual byte[] GetMacSecret()
- {
- return this.secret;
- }
-
- /**
- * @return the current write sequence number
- */
- public virtual long SequenceNumber
- {
- get { return this.seqNo; }
- }
-
- /**
- * Increment the current write sequence number
- */
- public virtual void IncSequenceNumber()
- {
- this.seqNo++;
- }
-
- /**
- * @return The Keysize of the mac.
- */
- public virtual int Size
- {
- get { return mac.GetMacSize(); }
- }
-
- /**
- * Calculate the mac for some given data.
- * <p/>
- * TlsMac will keep track of the sequence number internally.
- *
- * @param type The message type of the message.
- * @param message A byte-buffer containing the message.
- * @param offset The number of bytes to skip, before the message starts.
- * @param len The length of the message.
- * @return A new byte-buffer containing the mac value.
- */
- public virtual byte[] CalculateMac(ContentType type, byte[] message, int offset, int len)
- {
+ /// <remarks>
+ /// A generic TLS MAC implementation, which can be used with any kind of
+ /// IDigest to act as an HMAC.
+ /// </remarks>
+ public class TlsMac
+ {
+ protected long seqNo;
+ protected byte[] secret;
+ protected HMac mac;
+
+ /**
+ * Generate a new instance of an TlsMac.
+ *
+ * @param digest The digest to use.
+ * @param key_block A byte-array where the key for this mac is located.
+ * @param offset The number of bytes to skip, before the key starts in the buffer.
+ * @param len The length of the key.
+ */
+ public TlsMac(
+ IDigest digest,
+ byte[] key_block,
+ int offset,
+ int len)
+ {
+ this.seqNo = 0;
+
+ KeyParameter param = new KeyParameter(key_block, offset, len);
+
+ this.secret = Arrays.Clone(param.GetKey());
+
+ this.mac = new HMac(digest);
+ this.mac.Init(param);
+ }
+
+ /**
+ * @return the MAC write secret
+ */
+ public virtual byte[] GetMacSecret()
+ {
+ return this.secret;
+ }
+
+ /**
+ * @return the current write sequence number
+ */
+ public virtual long SequenceNumber
+ {
+ get { return this.seqNo; }
+ }
+
+ /**
+ * Increment the current write sequence number
+ */
+ public virtual void IncSequenceNumber()
+ {
+ this.seqNo++;
+ }
+
+ /**
+ * @return The Keysize of the mac.
+ */
+ public virtual int Size
+ {
+ get { return mac.GetMacSize(); }
+ }
+
+ /**
+ * Calculate the mac for some given data.
+ * <p/>
+ * TlsMac will keep track of the sequence number internally.
+ *
+ * @param type The message type of the message.
+ * @param message A byte-buffer containing the message.
+ * @param offset The number of bytes to skip, before the message starts.
+ * @param len The length of the message.
+ * @return A new byte-buffer containing the mac value.
+ */
+ public virtual byte[] CalculateMac(byte type, byte[] message, int offset, int len)
+ {
//bool isTls = context.ServerVersion.FullVersion >= ProtocolVersion.TLSv10.FullVersion;
bool isTls = true;
byte[] macHeader = new byte[isTls ? 13 : 11];
- TlsUtilities.WriteUint64(seqNo++, macHeader, 0);
- TlsUtilities.WriteUint8((byte)type, macHeader, 8);
+ TlsUtilities.WriteUint64(seqNo++, macHeader, 0);
+ TlsUtilities.WriteUint8(type, macHeader, 8);
if (isTls)
{
TlsUtilities.WriteVersion(macHeader, 9);
}
- TlsUtilities.WriteUint16(len, macHeader, 11);
+ TlsUtilities.WriteUint16(len, macHeader, 11);
mac.BlockUpdate(macHeader, 0, macHeader.Length);
- mac.BlockUpdate(message, offset, len);
- return MacUtilities.DoFinal(mac);
- }
+ mac.BlockUpdate(message, offset, len);
+ return MacUtilities.DoFinal(mac);
+ }
- public virtual byte[] CalculateMacConstantTime(ContentType type, byte[] message, int offset, int len,
+ public virtual byte[] CalculateMacConstantTime(byte type, byte[] message, int offset, int len,
int fullLength, byte[] dummyData)
{
// Actual MAC only calculated on 'len' bytes
@@ -138,5 +138,5 @@ namespace Org.BouncyCastle.Crypto.Tls
return result;
}
- }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsNullCipher.cs b/crypto/src/crypto/tls/TlsNullCipher.cs
index b76f76d9c..3e2bfa847 100644
--- a/crypto/src/crypto/tls/TlsNullCipher.cs
+++ b/crypto/src/crypto/tls/TlsNullCipher.cs
@@ -2,27 +2,27 @@ using System;
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// A NULL cipher suite, for use during handshake.
- /// </summary>
- public class TlsNullCipher
- : TlsCipher
- {
- public virtual byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len)
- {
- return CopyData(plaintext, offset, len);
- }
+ /// <summary>
+ /// A NULL cipher suite, for use during handshake.
+ /// </summary>
+ public class TlsNullCipher
+ : TlsCipher
+ {
+ public virtual byte[] EncodePlaintext(byte type, byte[] plaintext, int offset, int len)
+ {
+ return CopyData(plaintext, offset, len);
+ }
- public virtual byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len)
- {
- return CopyData(ciphertext, offset, len);
- }
+ public virtual byte[] DecodeCiphertext(byte type, byte[] ciphertext, int offset, int len)
+ {
+ return CopyData(ciphertext, offset, len);
+ }
- protected virtual byte[] CopyData(byte[] text, int offset, int len)
- {
- byte[] result = new byte[len];
- Array.Copy(text, offset, result, 0, len);
- return result;
- }
- }
+ protected virtual byte[] CopyData(byte[] text, int offset, int len)
+ {
+ byte[] result = new byte[len];
+ Array.Copy(text, offset, result, 0, len);
+ return result;
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsProtocolHandler.cs b/crypto/src/crypto/tls/TlsProtocolHandler.cs
index 0a970d251..c538229dc 100644
--- a/crypto/src/crypto/tls/TlsProtocolHandler.cs
+++ b/crypto/src/crypto/tls/TlsProtocolHandler.cs
@@ -40,8 +40,6 @@ namespace Org.BouncyCastle.Crypto.Tls
private const short CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED = 11;
private const short CS_DONE = 12;
- private static readonly byte[] emptybuf = new byte[0];
-
private static readonly string TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
/*
@@ -69,8 +67,8 @@ namespace Org.BouncyCastle.Crypto.Tls
private TlsClientContextImpl tlsClientContext = null;
private TlsClient tlsClient = null;
- private CipherSuite[] offeredCipherSuites = null;
- private CompressionMethod[] offeredCompressionMethods = null;
+ private int[] offeredCipherSuites = null;
+ private byte[] offeredCompressionMethods = null;
private TlsKeyExchange keyExchange = null;
private TlsAuthentication authentication = null;
private CertificateRequest certificateRequest = null;
@@ -122,15 +120,15 @@ namespace Org.BouncyCastle.Crypto.Tls
}
internal void ProcessData(
- ContentType protocol,
- byte[] buf,
- int offset,
- int len)
+ byte contentType,
+ byte[] buf,
+ int offset,
+ int len)
{
/*
* Have a look at the protocol type, and add it to the correct queue.
*/
- switch (protocol)
+ switch (contentType)
{
case ContentType.change_cipher_spec:
ProcessChangeCipherSpec(buf, offset, len);
@@ -177,7 +175,7 @@ namespace Org.BouncyCastle.Crypto.Tls
byte[] beginning = new byte[4];
handshakeQueue.Read(beginning, 0, 4, 0);
MemoryStream bis = new MemoryStream(beginning, false);
- HandshakeType type = (HandshakeType)TlsUtilities.ReadUint8(bis);
+ byte handshakeType = TlsUtilities.ReadUint8(bis);
int len = TlsUtilities.ReadUint24(bis);
/*
@@ -197,7 +195,7 @@ namespace Org.BouncyCastle.Crypto.Tls
* including, this finished message. [..] Note: [Also,] Hello Request
* messages are omitted from handshake hashes.
*/
- switch (type)
+ switch (handshakeType)
{
case HandshakeType.hello_request:
case HandshakeType.finished:
@@ -211,7 +209,7 @@ namespace Org.BouncyCastle.Crypto.Tls
/*
* Now, parse the message.
*/
- ProcessHandshakeMessage(type, buf);
+ ProcessHandshakeMessage(handshakeType, buf);
read = true;
}
}
@@ -219,14 +217,14 @@ namespace Org.BouncyCastle.Crypto.Tls
while (read);
}
- private void ProcessHandshakeMessage(HandshakeType type, byte[] buf)
+ private void ProcessHandshakeMessage(byte handshakeType, byte[] buf)
{
MemoryStream inStr = new MemoryStream(buf, false);
/*
* Check the type.
*/
- switch (type)
+ switch (handshakeType)
{
case HandshakeType.certificate:
{
@@ -324,7 +322,7 @@ namespace Org.BouncyCastle.Crypto.Tls
* Find out which CipherSuite the server has chosen and check that
* it was one of the offered ones.
*/
- CipherSuite selectedCipherSuite = (CipherSuite)TlsUtilities.ReadUint16(inStr);
+ int selectedCipherSuite = TlsUtilities.ReadUint16(inStr);
if (!ArrayContains(offeredCipherSuites, selectedCipherSuite)
|| selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
{
@@ -337,7 +335,7 @@ namespace Org.BouncyCastle.Crypto.Tls
* Find out which CompressionMethod the server has chosen and check that
* it was one of the offered ones.
*/
- CompressionMethod selectedCompressionMethod = (CompressionMethod)TlsUtilities.ReadUint8(inStr);
+ byte selectedCompressionMethod = TlsUtilities.ReadUint8(inStr);
if (!ArrayContains(offeredCompressionMethods, selectedCompressionMethod))
{
this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
@@ -364,7 +362,7 @@ namespace Org.BouncyCastle.Crypto.Tls
* containing no extensions.
*/
- // ExtensionType -> byte[]
+ // Int32 -> byte[]
IDictionary serverExtensions = Platform.CreateHashtable();
if (inStr.Position < inStr.Length)
@@ -375,7 +373,7 @@ namespace Org.BouncyCastle.Crypto.Tls
MemoryStream ext = new MemoryStream(extBytes, false);
while (ext.Position < ext.Length)
{
- ExtensionType extType = (ExtensionType)TlsUtilities.ReadUint16(ext);
+ int extType = TlsUtilities.ReadUint16(ext);
byte[] extValue = TlsUtilities.ReadOpaque16(ext);
// Note: RFC 5746 makes a special case for EXT_RenegotiationInfo
@@ -431,7 +429,7 @@ namespace Org.BouncyCastle.Crypto.Tls
byte[] renegExtValue = (byte[])serverExtensions[ExtensionType.renegotiation_info];
if (!Arrays.ConstantTimeAreEqual(renegExtValue,
- CreateRenegotiationInfo(emptybuf)))
+ CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
{
this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
}
@@ -626,29 +624,11 @@ namespace Org.BouncyCastle.Crypto.Tls
this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
}
- int numTypes = TlsUtilities.ReadUint8(inStr);
- ClientCertificateType[] certificateTypes = new ClientCertificateType[numTypes];
- for (int i = 0; i < numTypes; ++i)
- {
- certificateTypes[i] = (ClientCertificateType)TlsUtilities.ReadUint8(inStr);
- }
-
- byte[] authorities = TlsUtilities.ReadOpaque16(inStr);
+ this.certificateRequest = CertificateRequest.Parse(//getContext(),
+ inStr);
AssertEmpty(inStr);
- IList authorityDNs = Platform.CreateArrayList();
-
- MemoryStream bis = new MemoryStream(authorities, false);
- while (bis.Position < bis.Length)
- {
- byte[] dnBytes = TlsUtilities.ReadOpaque16(bis);
- // TODO Switch to X500Name when available
- authorityDNs.Add(X509Name.GetInstance(Asn1Object.FromByteArray(dnBytes)));
- }
-
- this.certificateRequest = new CertificateRequest(certificateTypes,
- authorityDNs);
this.keyExchange.ValidateCertificateRequest(this.certificateRequest);
break;
@@ -855,7 +835,7 @@ namespace Org.BouncyCastle.Crypto.Tls
this.offeredCipherSuites = this.tlsClient.GetCipherSuites();
- // ExtensionType -> byte[]
+ // Int32 -> byte[]
this.clientExtensions = this.tlsClient.GetClientExtensions();
// Cipher Suites (and SCSV)
@@ -899,7 +879,7 @@ namespace Org.BouncyCastle.Crypto.Tls
TlsUtilities.WriteUint8((byte)offeredCompressionMethods.Length, outStr);
for (int i = 0; i < offeredCompressionMethods.Length; ++i)
{
- TlsUtilities.WriteUint8((byte)offeredCompressionMethods[i], outStr);
+ TlsUtilities.WriteUint8(offeredCompressionMethods[i], outStr);
}
}
@@ -908,7 +888,7 @@ namespace Org.BouncyCastle.Crypto.Tls
{
MemoryStream ext = new MemoryStream();
- foreach (ExtensionType extType in clientExtensions.Keys)
+ foreach (int extType in clientExtensions.Keys)
{
WriteExtension(ext, extType, (byte[])clientExtensions[extType]);
}
@@ -1009,7 +989,7 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
- private void SafeWriteMessage(ContentType type, byte[] buf, int offset, int len)
+ private void SafeWriteMessage(byte type, byte[] buf, int offset, int len)
{
try
{
@@ -1064,22 +1044,33 @@ namespace Org.BouncyCastle.Crypto.Tls
while (len > 0)
{
/*
- * Protect against known IV attack!
- *
- * DO NOT REMOVE THIS LINE, EXCEPT YOU KNOW EXACTLY WHAT
- * YOU ARE DOING HERE.
+ * RFC 5246 6.2.1. Zero-length fragments of Application data MAY be sent as they are
+ * potentially useful as a traffic analysis countermeasure.
+ *
+ * NOTE: Actually, implementations appear to have settled on 1/n-1 record splitting.
*/
- SafeWriteMessage(ContentType.application_data, emptybuf, 0, 0);
- /*
- * We are only allowed to write fragments up to 2^14 bytes.
- */
- int toWrite = System.Math.Min(len, 1 << 14);
-
- SafeWriteMessage(ContentType.application_data, buf, offset, toWrite);
+ //if (this.splitApplicationDataRecords)
+ {
+ /*
+ * Protect against known IV attack!
+ *
+ * DO NOT REMOVE THIS CODE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
+ */
+ SafeWriteMessage(ContentType.application_data, buf, offset, 1);
+ ++offset;
+ --len;
+ }
- offset += toWrite;
- len -= toWrite;
+ if (len > 0)
+ {
+ // Fragment data according to the current fragment limit.
+ //int toWrite = System.Math.Min(len, recordStream.GetPlaintextLimit());
+ int toWrite = System.Math.Min(len, 1 << 14);
+ SafeWriteMessage(ContentType.application_data, buf, offset, toWrite);
+ offset += toWrite;
+ len -= toWrite;
+ }
}
}
@@ -1112,7 +1103,7 @@ namespace Org.BouncyCastle.Crypto.Tls
* @param alertDescription The exact alert message.
* @throws IOException If alert was fatal.
*/
- private void FailWithError(AlertLevel alertLevel, AlertDescription alertDescription)
+ private void FailWithError(byte alertLevel, byte alertDescription)
{
/*
* Check if the connection is still open.
@@ -1144,11 +1135,9 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
- internal void SendAlert(AlertLevel alertLevel, AlertDescription alertDescription)
+ internal void SendAlert(byte alertLevel, byte alertDescription)
{
- byte[] error = new byte[2];
- error[0] = (byte)alertLevel;
- error[1] = (byte)alertDescription;
+ byte[] error = new byte[] { alertLevel, alertDescription };
rs.WriteMessage(ContentType.alert, error, 0, 2);
}
@@ -1197,7 +1186,7 @@ namespace Org.BouncyCastle.Crypto.Tls
get { return closed; }
}
- private static bool ArrayContains(CipherSuite[] a, CipherSuite n)
+ private static bool ArrayContains(byte[] a, byte n)
{
for (int i = 0; i < a.Length; ++i)
{
@@ -1207,7 +1196,7 @@ namespace Org.BouncyCastle.Crypto.Tls
return false;
}
- private static bool ArrayContains(CompressionMethod[] a, CompressionMethod n)
+ private static bool ArrayContains(int[] a, int n)
{
for (int i = 0; i < a.Length; ++i)
{
@@ -1224,9 +1213,9 @@ namespace Org.BouncyCastle.Crypto.Tls
return buf.ToArray();
}
- private static void WriteExtension(Stream output, ExtensionType extType, byte[] extValue)
+ private static void WriteExtension(Stream output, int extType, byte[] extValue)
{
- TlsUtilities.WriteUint16((int)extType, output);
+ TlsUtilities.WriteUint16(extType, output);
TlsUtilities.WriteOpaque16(extValue, output);
}
}
diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
index cadd643ca..9961fc9d1 100644
--- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
@@ -8,42 +8,42 @@ using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Tls
{
- internal class TlsPskKeyExchange
- : TlsKeyExchange
- {
- protected TlsClientContext context;
- protected KeyExchangeAlgorithm keyExchange;
- protected TlsPskIdentity pskIdentity;
+ internal class TlsPskKeyExchange
+ : TlsKeyExchange
+ {
+ protected TlsClientContext context;
+ protected int keyExchange;
+ protected TlsPskIdentity pskIdentity;
- protected byte[] psk_identity_hint = null;
+ protected byte[] psk_identity_hint = null;
- protected DHPublicKeyParameters dhAgreeServerPublicKey = null;
- protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null;
+ protected DHPublicKeyParameters dhAgreeServerPublicKey = null;
+ protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null;
protected AsymmetricKeyParameter serverPublicKey = null;
protected RsaKeyParameters rsaServerPublicKey = null;
- protected byte[] premasterSecret;
-
- internal TlsPskKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange,
- TlsPskIdentity pskIdentity)
- {
- switch (keyExchange)
- {
- case KeyExchangeAlgorithm.PSK:
- case KeyExchangeAlgorithm.RSA_PSK:
- case KeyExchangeAlgorithm.DHE_PSK:
- break;
- default:
- throw new ArgumentException("unsupported key exchange algorithm", "keyExchange");
- }
-
- this.context = context;
- this.keyExchange = keyExchange;
- this.pskIdentity = pskIdentity;
- }
-
- public virtual void SkipServerCertificate()
- {
+ protected byte[] premasterSecret;
+
+ internal TlsPskKeyExchange(TlsClientContext context, int keyExchange,
+ TlsPskIdentity pskIdentity)
+ {
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.PSK:
+ case KeyExchangeAlgorithm.RSA_PSK:
+ case KeyExchangeAlgorithm.DHE_PSK:
+ break;
+ default:
+ throw new ArgumentException("unsupported key exchange algorithm", "keyExchange");
+ }
+
+ this.context = context;
+ this.keyExchange = keyExchange;
+ this.pskIdentity = pskIdentity;
+ }
+
+ public virtual void SkipServerCertificate()
+ {
if (keyExchange == KeyExchangeAlgorithm.RSA_PSK)
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
@@ -51,13 +51,13 @@ namespace Org.BouncyCastle.Crypto.Tls
}
public virtual void ProcessServerCertificate(Certificate serverCertificate)
- {
+ {
if (keyExchange != KeyExchangeAlgorithm.RSA_PSK)
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- X509CertificateStructure x509Cert = serverCertificate.certs[0];
+ X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
try
@@ -88,107 +88,107 @@ namespace Org.BouncyCastle.Crypto.Tls
*/
}
- public virtual void SkipServerKeyExchange()
- {
+ public virtual void SkipServerKeyExchange()
+ {
if (keyExchange == KeyExchangeAlgorithm.DHE_PSK)
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- this.psk_identity_hint = new byte[0];
- }
-
- public virtual void ProcessServerKeyExchange(Stream input)
- {
- this.psk_identity_hint = TlsUtilities.ReadOpaque16(input);
-
- if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- byte[] pBytes = TlsUtilities.ReadOpaque16(input);
- byte[] gBytes = TlsUtilities.ReadOpaque16(input);
- byte[] YsBytes = TlsUtilities.ReadOpaque16(input);
-
- BigInteger p = new BigInteger(1, pBytes);
- BigInteger g = new BigInteger(1, gBytes);
- BigInteger Ys = new BigInteger(1, YsBytes);
-
- this.dhAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey(
- new DHPublicKeyParameters(Ys, new DHParameters(p, g)));
- }
- else if (this.psk_identity_hint.Length == 0)
- {
- // TODO Should we enforce that this message should have been skipped if hint is empty?
- //throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public virtual void SkipClientCredentials()
- {
- // OK
- }
-
- public virtual void ProcessClientCredentials(TlsCredentials clientCredentials)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- public virtual void GenerateClientKeyExchange(Stream output)
- {
- if (psk_identity_hint == null || psk_identity_hint.Length == 0)
- {
- pskIdentity.SkipIdentityHint();
- }
- else
- {
- pskIdentity.NotifyIdentityHint(psk_identity_hint);
- }
-
- byte[] psk_identity = pskIdentity.GetPskIdentity();
-
- TlsUtilities.WriteOpaque16(psk_identity, output);
-
- if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
- {
- this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(
- context.SecureRandom, this.rsaServerPublicKey, output);
- }
- else if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- this.dhAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(
- context.SecureRandom, this.dhAgreeServerPublicKey.Parameters, output);
- }
- }
-
- public virtual byte[] GeneratePremasterSecret()
- {
- byte[] psk = pskIdentity.GetPsk();
- byte[] other_secret = GenerateOtherSecret(psk.Length);
-
- MemoryStream buf = new MemoryStream(4 + other_secret.Length + psk.Length);
- TlsUtilities.WriteOpaque16(other_secret, buf);
- TlsUtilities.WriteOpaque16(psk, buf);
- return buf.ToArray();
- }
-
- protected virtual byte[] GenerateOtherSecret(int pskLength)
- {
- if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- return TlsDHUtilities.CalculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
- }
-
- if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
- {
- return this.premasterSecret;
- }
-
- return new byte[pskLength];
- }
+ this.psk_identity_hint = TlsUtilities.EmptyBytes;
+ }
+
+ public virtual void ProcessServerKeyExchange(Stream input)
+ {
+ this.psk_identity_hint = TlsUtilities.ReadOpaque16(input);
+
+ if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ byte[] pBytes = TlsUtilities.ReadOpaque16(input);
+ byte[] gBytes = TlsUtilities.ReadOpaque16(input);
+ byte[] YsBytes = TlsUtilities.ReadOpaque16(input);
+
+ BigInteger p = new BigInteger(1, pBytes);
+ BigInteger g = new BigInteger(1, gBytes);
+ BigInteger Ys = new BigInteger(1, YsBytes);
+
+ this.dhAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey(
+ new DHPublicKeyParameters(Ys, new DHParameters(p, g)));
+ }
+ else if (this.psk_identity_hint.Length == 0)
+ {
+ // TODO Should we enforce that this message should have been skipped if hint is empty?
+ //throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public virtual void SkipClientCredentials()
+ {
+ // OK
+ }
+
+ public virtual void ProcessClientCredentials(TlsCredentials clientCredentials)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ public virtual void GenerateClientKeyExchange(Stream output)
+ {
+ if (psk_identity_hint == null || psk_identity_hint.Length == 0)
+ {
+ pskIdentity.SkipIdentityHint();
+ }
+ else
+ {
+ pskIdentity.NotifyIdentityHint(psk_identity_hint);
+ }
+
+ byte[] psk_identity = pskIdentity.GetPskIdentity();
+
+ TlsUtilities.WriteOpaque16(psk_identity, output);
+
+ if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
+ {
+ this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(
+ context.SecureRandom, this.rsaServerPublicKey, output);
+ }
+ else if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ this.dhAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(
+ context.SecureRandom, this.dhAgreeServerPublicKey.Parameters, output);
+ }
+ }
+
+ public virtual byte[] GeneratePremasterSecret()
+ {
+ byte[] psk = pskIdentity.GetPsk();
+ byte[] other_secret = GenerateOtherSecret(psk.Length);
+
+ MemoryStream buf = new MemoryStream(4 + other_secret.Length + psk.Length);
+ TlsUtilities.WriteOpaque16(other_secret, buf);
+ TlsUtilities.WriteOpaque16(psk, buf);
+ return buf.ToArray();
+ }
+
+ protected virtual byte[] GenerateOtherSecret(int pskLength)
+ {
+ if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ return TlsDHUtilities.CalculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
+ }
+
+ if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
+ {
+ return this.premasterSecret;
+ }
+
+ return new byte[pskLength];
+ }
protected virtual RsaKeyParameters ValidateRsaPublicKey(RsaKeyParameters key)
{
diff --git a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs
index ad61f08de..aad482316 100644
--- a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs
@@ -11,117 +11,117 @@ using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Tls
{
- /// <summary>
- /// TLS 1.0 RSA key exchange.
- /// </summary>
- internal class TlsRsaKeyExchange
- : TlsKeyExchange
- {
- protected TlsClientContext context;
+ /// <summary>
+ /// TLS 1.0 RSA key exchange.
+ /// </summary>
+ internal class TlsRsaKeyExchange
+ : TlsKeyExchange
+ {
+ protected TlsClientContext context;
- protected AsymmetricKeyParameter serverPublicKey = null;
+ protected AsymmetricKeyParameter serverPublicKey = null;
protected RsaKeyParameters rsaServerPublicKey = null;
protected byte[] premasterSecret;
- internal TlsRsaKeyExchange(TlsClientContext context)
- {
- this.context = context;
- }
-
- public virtual void SkipServerCertificate()
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public virtual void ProcessServerCertificate(Certificate serverCertificate)
- {
- X509CertificateStructure x509Cert = serverCertificate.certs[0];
- SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
-
- try
- {
- this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo);
- }
+ internal TlsRsaKeyExchange(TlsClientContext context)
+ {
+ this.context = context;
+ }
+
+ public virtual void SkipServerCertificate()
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public virtual void ProcessServerCertificate(Certificate serverCertificate)
+ {
+ X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
+ SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
+
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo);
+ }
// catch (RuntimeException)
- catch (Exception)
- {
- throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
- }
-
- // Sanity check the PublicKeyFactory
- if (this.serverPublicKey.IsPrivate)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- this.rsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.serverPublicKey);
-
- TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment);
-
- // TODO
- /*
- * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the
- * signing algorithm for the certificate must be the same as the algorithm for the
- * certificate key."
- */
- }
-
- public virtual void SkipServerKeyExchange()
- {
- // OK
- }
-
- public virtual void ProcessServerKeyExchange(Stream input)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest)
- {
- ClientCertificateType[] types = certificateRequest.CertificateTypes;
- foreach (ClientCertificateType type in types)
- {
- switch (type)
- {
- case ClientCertificateType.rsa_sign:
- case ClientCertificateType.dss_sign:
- case ClientCertificateType.ecdsa_sign:
- break;
- default:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- }
-
- public virtual void SkipClientCredentials()
- {
- // OK
- }
-
- public virtual void ProcessClientCredentials(TlsCredentials clientCredentials)
- {
- if (!(clientCredentials is TlsSignerCredentials))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
+ catch (Exception)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ // Sanity check the PublicKeyFactory
+ if (this.serverPublicKey.IsPrivate)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ this.rsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.serverPublicKey);
+
+ TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment);
+
+ // TODO
+ /*
+ * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the
+ * signing algorithm for the certificate must be the same as the algorithm for the
+ * certificate key."
+ */
+ }
+
+ public virtual void SkipServerKeyExchange()
+ {
+ // OK
+ }
+
+ public virtual void ProcessServerKeyExchange(Stream input)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest)
+ {
+ byte[] types = certificateRequest.CertificateTypes;
+ foreach (byte type in types)
+ {
+ switch (type)
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.ecdsa_sign:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public virtual void SkipClientCredentials()
+ {
+ // OK
+ }
+
+ public virtual void ProcessClientCredentials(TlsCredentials clientCredentials)
+ {
+ if (!(clientCredentials is TlsSignerCredentials))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
public virtual void GenerateClientKeyExchange(Stream output)
- {
- this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(
- context.SecureRandom, this.rsaServerPublicKey, output);
- }
-
- public virtual byte[] GeneratePremasterSecret()
- {
- byte[] tmp = this.premasterSecret;
- this.premasterSecret = null;
- return tmp;
- }
-
- // Would be needed to process RSA_EXPORT server key exchange
+ {
+ this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(
+ context.SecureRandom, this.rsaServerPublicKey, output);
+ }
+
+ public virtual byte[] GeneratePremasterSecret()
+ {
+ byte[] tmp = this.premasterSecret;
+ this.premasterSecret = null;
+ return tmp;
+ }
+
+ // Would be needed to process RSA_EXPORT server key exchange
// protected virtual void ProcessRsaServerKeyExchange(Stream input, ISigner signer)
// {
// Stream sigIn = input;
@@ -150,16 +150,16 @@ namespace Org.BouncyCastle.Crypto.Tls
// }
protected virtual RsaKeyParameters ValidateRsaPublicKey(RsaKeyParameters key)
- {
- // TODO What is the minimum bit length required?
+ {
+ // TODO What is the minimum bit length required?
// key.Modulus.BitLength;
- if (!key.Exponent.IsProbablePrime(2))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
+ if (!key.Exponent.IsProbablePrime(2))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
- return key;
- }
- }
+ return key;
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
index cb4e26e58..950be87ba 100644
--- a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
@@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Crypto.Tls
: TlsKeyExchange
{
protected TlsClientContext context;
- protected KeyExchangeAlgorithm keyExchange;
+ protected int keyExchange;
protected TlsSigner tlsSigner;
protected byte[] identity;
protected byte[] password;
@@ -33,7 +33,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected BigInteger B = null;
protected Srp6Client srpClient = new Srp6Client();
- internal TlsSrpKeyExchange(TlsClientContext context, KeyExchangeAlgorithm keyExchange,
+ internal TlsSrpKeyExchange(TlsClientContext context, int keyExchange,
byte[] identity, byte[] password)
{
switch (keyExchange)
@@ -72,7 +72,7 @@ namespace Org.BouncyCastle.Crypto.Tls
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- X509CertificateStructure x509Cert = serverCertificate.certs[0];
+ X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
try
diff --git a/crypto/src/crypto/tls/TlsStreamCipher.cs b/crypto/src/crypto/tls/TlsStreamCipher.cs
index 65d6054ff..35f794d96 100644
--- a/crypto/src/crypto/tls/TlsStreamCipher.cs
+++ b/crypto/src/crypto/tls/TlsStreamCipher.cs
@@ -18,40 +18,40 @@ namespace Org.BouncyCastle.Crypto.Tls
protected TlsMac readMac;
public TlsStreamCipher(TlsClientContext context, IStreamCipher encryptCipher,
- IStreamCipher decryptCipher, IDigest writeDigest, IDigest readDigest, int cipherKeySize)
- {
- this.context = context;
- this.encryptCipher = encryptCipher;
- this.decryptCipher = decryptCipher;
+ IStreamCipher decryptCipher, IDigest writeDigest, IDigest readDigest, int cipherKeySize)
+ {
+ this.context = context;
+ this.encryptCipher = encryptCipher;
+ this.decryptCipher = decryptCipher;
int prfSize = (2 * cipherKeySize) + writeDigest.GetDigestSize()
+ readDigest.GetDigestSize();
- SecurityParameters securityParameters = context.SecurityParameters;
+ SecurityParameters securityParameters = context.SecurityParameters;
- byte[] keyBlock = TlsUtilities.PRF(securityParameters.masterSecret, "key expansion",
- TlsUtilities.Concat(securityParameters.serverRandom, securityParameters.clientRandom),
- prfSize);
+ byte[] keyBlock = TlsUtilities.PRF(securityParameters.masterSecret, "key expansion",
+ TlsUtilities.Concat(securityParameters.serverRandom, securityParameters.clientRandom),
+ prfSize);
- int offset = 0;
+ int offset = 0;
- // Init MACs
- writeMac = CreateTlsMac(writeDigest, keyBlock, ref offset);
- readMac = CreateTlsMac(readDigest, keyBlock, ref offset);
+ // Init MACs
+ writeMac = CreateTlsMac(writeDigest, keyBlock, ref offset);
+ readMac = CreateTlsMac(readDigest, keyBlock, ref offset);
- // Build keys
- KeyParameter encryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize);
- KeyParameter decryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize);
+ // Build keys
+ KeyParameter encryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize);
+ KeyParameter decryptKey = CreateKeyParameter(keyBlock, ref offset, cipherKeySize);
- if (offset != prfSize)
+ if (offset != prfSize)
throw new TlsFatalAlert(AlertDescription.internal_error);
// Init Ciphers
encryptCipher.Init(true, encryptKey);
decryptCipher.Init(false, decryptKey);
- }
+ }
- public byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len)
+ public byte[] EncodePlaintext(byte type, byte[] plaintext, int offset, int len)
{
byte[] mac = writeMac.CalculateMac(type, plaintext, offset, len);
int size = len + mac.Length;
@@ -64,7 +64,7 @@ namespace Org.BouncyCastle.Crypto.Tls
return outbuf;
}
- public byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len)
+ public byte[] DecodeCiphertext(byte type, byte[] ciphertext, int offset, int len)
{
byte[] deciphered = new byte[len];
decryptCipher.ProcessBytes(ciphertext, offset, len, deciphered, 0);
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index dca842a80..5ed659ce7 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections;
using System.IO;
using System.Text;
@@ -16,6 +17,41 @@ namespace Org.BouncyCastle.Crypto.Tls
/// <remarks>Some helper functions for MicroTLS.</remarks>
public class TlsUtilities
{
+ public static readonly byte[] EmptyBytes = new byte[0];
+
+ public static void CheckUint8(int i)
+ {
+ if (!IsValidUint8(i))
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ public static void CheckUint16(int i)
+ {
+ if (!IsValidUint16(i))
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ public static void CheckUint24(int i)
+ {
+ if (!IsValidUint24(i))
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ public static bool IsValidUint8(int i)
+ {
+ return (i & 0xFF) == i;
+ }
+
+ public static bool IsValidUint16(int i)
+ {
+ return (i & 0xFFFF) == i;
+ }
+
+ public static bool IsValidUint24(int i)
+ {
+ return (i & 0xFFFFFF) == i;
+ }
+
internal static void WriteUint8(byte i, Stream os)
{
os.WriteByte(i);
@@ -99,6 +135,13 @@ namespace Org.BouncyCastle.Crypto.Tls
os.Write(uints, 0, uints.Length);
}
+ public static void WriteUint8ArrayWithUint8Length(byte[] uints, Stream output)
+ {
+ CheckUint8(uints.Length);
+ WriteUint8((byte)uints.Length, output);
+ WriteUint8Array(uints, output);
+ }
+
internal static void WriteUint16Array(int[] uints, Stream os)
{
for (int i = 0; i < uints.Length; ++i)
@@ -140,6 +183,16 @@ namespace Org.BouncyCastle.Crypto.Tls
return (i1 << 16) | (i2 << 8) | i3;
}
+ public static byte[] ReadFully(int length, Stream input)
+ {
+ if (length < 1)
+ return EmptyBytes;
+ byte[] buf = new byte[length];
+ if (length != Streams.ReadFully(input, buf))
+ throw new EndOfStreamException();
+ return buf;
+ }
+
internal static void ReadFully(byte[] buf, Stream inStr)
{
if (Streams.ReadFully(inStr, buf, 0, buf.Length) < buf.Length)
@@ -162,6 +215,12 @@ namespace Org.BouncyCastle.Crypto.Tls
return bytes;
}
+ public static byte[] ReadOpaque24(Stream input)
+ {
+ int length = ReadUint24(input);
+ return ReadFully(length, input);
+ }
+
internal static void CheckVersion(byte[] readVersion)
{
if ((readVersion[0] != 3) || (readVersion[1] != 1))
@@ -180,6 +239,30 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
+ public static Asn1Object ReadAsn1Object(byte[] encoding)
+ {
+ Asn1InputStream asn1 = new Asn1InputStream(encoding);
+ Asn1Object result = asn1.ReadObject();
+ if (null == result)
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ if (null != asn1.ReadObject())
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ return result;
+ }
+
+ public static Asn1Object ReadDerObject(byte[] encoding)
+ {
+ /*
+ * NOTE: The current ASN.1 parsing code can't enforce DER-only parsing, but since DER is
+ * canonical, we can check it by re-encoding the result and comparing to the original.
+ */
+ Asn1Object result = ReadAsn1Object(encoding);
+ byte[] check = result.GetEncoded(Asn1Encodable.Der);
+ if (!Arrays.AreEqual(check, encoding))
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ return result;
+ }
+
internal static void WriteGmtUnixTime(byte[] buf, int offset)
{
int t = (int)(DateTimeUtilities.CurrentUnixMs() / 1000L);
@@ -201,6 +284,35 @@ namespace Org.BouncyCastle.Crypto.Tls
buf[offset + 1] = 1;
}
+ public static void EncodeSupportedSignatureAlgorithms(IList supportedSignatureAlgorithms, bool allowAnonymous,
+ Stream output)
+ {
+ if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.Count < 1
+ || supportedSignatureAlgorithms.Count >= (1 << 15))
+ {
+ throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms");
+ }
+
+ // supported_signature_algorithms
+ int length = 2 * supportedSignatureAlgorithms.Count;
+ TlsUtilities.CheckUint16(length);
+ TlsUtilities.WriteUint16(length, output);
+
+ foreach (SignatureAndHashAlgorithm entry in supportedSignatureAlgorithms)
+ {
+ if (!allowAnonymous && entry.Signature == SignatureAlgorithm.anonymous)
+ {
+ /*
+ * RFC 5246 7.4.1.4.1 The "anonymous" value is meaningless in this context but used
+ * in Section 7.4.3. It MUST NOT appear in this extension.
+ */
+ throw new ArgumentException(
+ "SignatureAlgorithm.anonymous MUST NOT appear in the signature_algorithms extension");
+ }
+ entry.Encode(output);
+ }
+ }
+
private static void hmac_hash(IDigest digest, byte[] secret, byte[] seed, byte[] output)
{
HMac mac = new HMac(digest);
|