Initial Commit

This commit is contained in:
2023-06-21 12:46:23 -04:00
commit c70248a520
1352 changed files with 336780 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
using System;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>
/// A certificate verifyer, that will always return true.
/// <pre>
/// DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING.
/// </pre>
/// </remarks>
public class AlwaysValidVerifyer
: ICertificateVerifyer
{
/// <summary>Return true.</summary>
public bool IsValid(
X509CertificateStructure[] certs)
{
return true;
}
}
}

View File

@@ -0,0 +1,125 @@
using System;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>
/// A queue for bytes.
/// <p>
/// This file could be more optimized.
/// </p>
/// </remarks>
public class ByteQueue
{
/// <returns>The smallest number which can be written as 2^x which is bigger than i.</returns>
public static int NextTwoPow(
int i)
{
/*
* This code is based of a lot of code I found on the Internet
* which mostly referenced a book called "Hacking delight".
*
*/
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
return i + 1;
}
/**
* The initial size for our buffer.
*/
private const int InitBufSize = 1024;
/**
* The buffer where we store our data.
*/
private byte[] databuf = new byte[ByteQueue.InitBufSize];
/**
* How many bytes at the beginning of the buffer are skipped.
*/
private int skipped = 0;
/**
* How many bytes in the buffer are valid data.
*/
private int available = 0;
/// <summary>Read data from the buffer.</summary>
/// <param name="buf">The buffer where the read data will be copied to.</param>
/// <param name="offset">How many bytes to skip at the beginning of buf.</param>
/// <param name="len">How many bytes to read at all.</param>
/// <param name="skip">How many bytes from our data to skip.</param>
public void Read(
byte[] buf,
int offset,
int len,
int skip)
{
if ((available - skip) < len)
{
throw new TlsException("Not enough data to read");
}
if ((buf.Length - offset) < len)
{
throw new TlsException("Buffer size of " + buf.Length + " is too small for a read of " + len + " bytes");
}
Array.Copy(databuf, skipped + skip, buf, offset, len);
}
/// <summary>Add some data to our buffer.</summary>
/// <param name="data">A byte-array to read data from.</param>
/// <param name="offset">How many bytes to skip at the beginning of the array.</param>
/// <param name="len">How many bytes to read from the array.</param>
public void AddData(
byte[] data,
int offset,
int len)
{
if ((skipped + available + len) > databuf.Length)
{
byte[] tmp = new byte[ByteQueue.NextTwoPow(data.Length)];
Array.Copy(databuf, skipped, tmp, 0, available);
skipped = 0;
databuf = tmp;
}
Array.Copy(data, offset, databuf, skipped + available, len);
available += len;
}
/// <summary>Remove some bytes from our data from the beginning.</summary>
/// <param name="i">How many bytes to remove.</param>
public void RemoveData(
int i)
{
if (i > available)
{
throw new TlsException("Cannot remove " + i + " bytes, only got " + available);
}
/*
* Skip the data.
*/
available -= i;
skipped += i;
/*
* If more than half of our data is skipped, we will move the data
* in the buffer.
*/
if (skipped > (databuf.Length / 2))
{
Array.Copy(databuf, skipped, databuf, 0, available);
skipped = 0;
}
}
/// <summary>The number of bytes which are available in this buffer.</summary>
public int Available
{
get { return available; }
}
}
}

View File

@@ -0,0 +1,78 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Crypto.Tls
{
/**
* A representation for a certificate chain as used by an tls server.
*/
public class Certificate
{
/**
* The certificates.
*/
internal X509CertificateStructure[] certs;
/**
* Parse the ServerCertificate message.
*
* @param is 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)
{
X509CertificateStructure[] certs;
int left = TlsUtilities.ReadUint24(inStr);
ArrayList tmp = new ArrayList();
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);
Asn1InputStream ais = new Asn1InputStream(bis);
Asn1Object o = ais.ReadObject();
tmp.Add(X509CertificateStructure.GetInstance(o));
// if (bis.available() > 0)
if (bis.Position < bis.Length)
{
throw new ArgumentException("Sorry, there is garbage data left after the certificate");
}
}
// certs = new X509CertificateStructure[tmp.size()];
// for (int i = 0; i < tmp.size(); i++)
// {
// certs[i] = (X509CertificateStructure)tmp.elementAt(i);
// }
certs = (X509CertificateStructure[]) tmp.ToArray(typeof(X509CertificateStructure));
return new Certificate(certs);
}
/**
* Private constructure from an cert array.
*
* @param certs The certs the chain should contain.
*/
private Certificate(
X509CertificateStructure[] certs)
{
this.certs = certs;
}
/// <returns>An array which contains the certs, this chain contains.</returns>
public X509CertificateStructure[] GetCerts()
{
// X509CertificateStructure[] result = new X509CertificateStructure[certs.Length];
// Array.Copy(certs, 0, result, 0, certs.Length);
// return result;
return (X509CertificateStructure[]) certs.Clone();
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using Org.BouncyCastle.Crypto.Digests;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>A combined hash, which implements md5(m) || sha1(m).</remarks>
public class CombinedHash
: IDigest
{
private IDigest md5 = new MD5Digest();
private IDigest sha1 = new Sha1Digest();
/// <seealso cref="IDigest.AlgorithmName"/>
public string AlgorithmName
{
get
{
return md5.AlgorithmName + " and " + sha1.AlgorithmName + " for TLS 1.0";
}
}
/// <seealso cref="IDigest.GetByteLength"/>
public int GetByteLength()
{
return System.Math.Max(md5.GetByteLength(), sha1.GetByteLength());
}
/// <seealso cref="IDigest.GetDigestSize"/>
public int GetDigestSize()
{
return md5.GetDigestSize() + sha1.GetDigestSize();
}
/// <seealso cref="IDigest.Update"/>
public void Update(
byte input)
{
md5.Update(input);
sha1.Update(input);
}
/// <seealso cref="IDigest.BlockUpdate"/>
public void BlockUpdate(
byte[] input,
int inOff,
int len)
{
md5.BlockUpdate(input, inOff, len);
sha1.BlockUpdate(input, inOff, len);
}
/// <seealso cref="IDigest.DoFinal"/>
public int DoFinal(
byte[] output,
int outOff)
{
int i1 = md5.DoFinal(output, outOff);
int i2 = sha1.DoFinal(output, outOff + i1);
return i1 + i2;
}
/// <seealso cref="IDigest.Reset"/>
public void Reset()
{
md5.Reset();
sha1.Reset();
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>
/// This should be implemented by any class which can find out, if a given
/// certificate chain is beeing accepted by an client.
/// </remarks>
public interface ICertificateVerifyer
{
/// <param name="certs">The certs, which are part of the chain.</param>
/// <returns>True, if the chain is accepted, false otherwise</returns>
bool IsValid(X509CertificateStructure[] certs);
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>An implementation of the TLS 1.0 record layer.</remarks>
public class RecordStream
{
private TlsProtocolHandler handler;
private Stream inStr;
private Stream outStr;
internal CombinedHash hash1;
internal CombinedHash hash2;
internal TlsCipherSuite readSuite = null;
internal TlsCipherSuite writeSuite = null;
internal RecordStream(
TlsProtocolHandler handler,
Stream inStr,
Stream outStr)
{
this.handler = handler;
this.inStr = inStr;
this.outStr = outStr;
hash1 = new CombinedHash();
hash2 = new CombinedHash();
this.readSuite = new TlsNullCipherSuite();
this.writeSuite = this.readSuite;
}
public void ReadData()
{
short type = TlsUtilities.ReadUint8(inStr);
TlsUtilities.CheckVersion(inStr, handler);
int size = TlsUtilities.ReadUint16(inStr);
byte[] buf = DecodeAndVerify(type, inStr, size);
handler.ProcessData(type, buf, 0, buf.Length);
}
internal byte[] DecodeAndVerify(
short type,
Stream inStr,
int len)
{
byte[] buf = new byte[len];
TlsUtilities.ReadFully(buf, inStr);
byte[] result = readSuite.DecodeCiphertext(type, buf, 0, buf.Length, handler);
return result;
}
internal void WriteMessage(
short type,
byte[] message,
int offset,
int len)
{
if (type == 22)
{
hash1.BlockUpdate(message, offset, len);
hash2.BlockUpdate(message, offset, len);
}
byte[] ciphertext = writeSuite.EncodePlaintext(type, message, offset, len);
byte[] writeMessage = new byte[ciphertext.Length + 5];
TlsUtilities.WriteUint8(type, writeMessage, 0);
TlsUtilities.WriteUint8((short)3, writeMessage, 1);
TlsUtilities.WriteUint8((short)1, writeMessage, 2);
TlsUtilities.WriteUint16(ciphertext.Length, writeMessage, 3);
Array.Copy(ciphertext, 0, writeMessage, 5, ciphertext.Length);
outStr.Write(writeMessage, 0, writeMessage.Length);
outStr.Flush();
}
internal void Close()
{
IOException e = null;
try
{
inStr.Close();
}
catch (IOException ex)
{
e = ex;
}
try
{
// NB: This is harmless if outStr == inStr
outStr.Close();
}
catch (IOException ex)
{
e = ex;
}
if (e != null)
{
throw e;
}
}
internal void Flush()
{
outStr.Flush();
}
}
}

View File

@@ -0,0 +1,196 @@
using System;
using System.Text;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>A generic TLS 1.0 block cipher suite. This can be used for AES or 3DES for example.</remarks>
public class TlsBlockCipherCipherSuite
: TlsCipherSuite
{
private IBlockCipher encryptCipher;
private IBlockCipher decryptCipher;
private IDigest writeDigest;
private IDigest readDigest;
private int cipherKeySize;
private short keyExchange;
private TlsMac writeMac;
private TlsMac readMac;
internal TlsBlockCipherCipherSuite(
IBlockCipher encrypt,
IBlockCipher decrypt,
IDigest writeDigest,
IDigest readDigest,
int cipherKeySize,
short keyExchange)
{
this.encryptCipher = encrypt;
this.decryptCipher = decrypt;
this.writeDigest = writeDigest;
this.readDigest = readDigest;
this.cipherKeySize = cipherKeySize;
this.keyExchange = keyExchange;
}
internal override void Init(byte[] ms, byte[] cr, byte[] sr)
{
int prfSize = (2 * cipherKeySize) + (2 * writeDigest.GetDigestSize())
+ (2 * encryptCipher.GetBlockSize());
byte[] key_block = new byte[prfSize];
byte[] random = new byte[cr.Length + sr.Length];
Array.Copy(cr, 0, random, sr.Length, cr.Length);
Array.Copy(sr, 0, random, 0, sr.Length);
TlsUtilities.PRF(ms, TlsUtilities.ToByteArray("key expansion"), random, key_block);
int offset = 0;
// Init MACs
writeMac = new TlsMac(writeDigest, key_block, offset, writeDigest
.GetDigestSize());
offset += writeDigest.GetDigestSize();
readMac = new TlsMac(readDigest, key_block, offset, readDigest
.GetDigestSize());
offset += readDigest.GetDigestSize();
// Init Ciphers
this.initCipher(true, encryptCipher, key_block, cipherKeySize, offset,
offset + (cipherKeySize * 2));
offset += cipherKeySize;
this.initCipher(false, decryptCipher, key_block, cipherKeySize, offset,
offset + cipherKeySize + decryptCipher.GetBlockSize());
}
private void initCipher(bool forEncryption, IBlockCipher cipher,
byte[] key_block, int key_size, int key_offset, int iv_offset)
{
KeyParameter key_parameter = new KeyParameter(key_block, key_offset,
key_size);
ParametersWithIV parameters_with_iv = new ParametersWithIV(
key_parameter, key_block, iv_offset, cipher.GetBlockSize());
cipher.Init(forEncryption, parameters_with_iv);
}
internal override byte[] EncodePlaintext(
short type,
byte[] plaintext,
int offset,
int len)
{
int blocksize = encryptCipher.GetBlockSize();
int paddingsize = blocksize
- ((len + writeMac.Size + 1) % blocksize);
int totalsize = len + writeMac.Size + paddingsize + 1;
byte[] outbuf = new byte[totalsize];
Array.Copy(plaintext, offset, outbuf, 0, len);
byte[] mac = writeMac.CalculateMac(type, plaintext, offset, len);
Array.Copy(mac, 0, outbuf, len, mac.Length);
int paddoffset = len + mac.Length;
for (int i = 0; i <= paddingsize; i++)
{
outbuf[i + paddoffset] = (byte)paddingsize;
}
for (int i = 0; i < totalsize; i += blocksize)
{
encryptCipher.ProcessBlock(outbuf, i, outbuf, i);
}
return outbuf;
}
internal override byte[] DecodeCiphertext(
short type,
byte[] ciphertext,
int offset,
int len,
TlsProtocolHandler handler)
{
int blocksize = decryptCipher.GetBlockSize();
bool decrypterror = false;
/*
* Decrypt all the ciphertext using the blockcipher
*/
for (int i = 0; i < len; i += blocksize)
{
decryptCipher.ProcessBlock(ciphertext, i + offset, ciphertext, i
+ offset);
}
/*
* Check if padding is correct
*/
int paddingsize = ciphertext[offset + len - 1];
if (offset + len - 1 - paddingsize < 0)
{
/*
* This would lead to an negativ array index, so this padding
* must be incorrect!
*/
decrypterror = true;
paddingsize = 0;
}
else
{
/*
* Now, check all the padding-bytes.
*/
for (int i = 0; i <= paddingsize; i++)
{
if (ciphertext[offset + len - 1 - i] != paddingsize)
{
/* Wrong padding */
decrypterror = true;
}
}
}
/*
* We now don't care if padding verification has failed or not,
* we will calculate the mac to give an attacker no kind of timing
* profile he can use to find out if mac verification failed or
* padding verification failed.
*/
int plaintextlength = len - readMac.Size - paddingsize - 1;
byte[] calculatedMac = readMac.CalculateMac(type, ciphertext, offset,
plaintextlength);
/*
* Check all bytes in the mac.
*/
for (int i = 0; i < calculatedMac.Length; i++)
{
if (ciphertext[offset + plaintextlength + i] != calculatedMac[i])
{
decrypterror = true;
}
}
/*
* Now, it is save to fail.
*/
if (decrypterror)
{
handler.FailWithError(TlsProtocolHandler.AL_fatal,
TlsProtocolHandler.AP_bad_record_mac);
}
byte[] plaintext = new byte[plaintextlength];
Array.Copy(ciphertext, offset, plaintext, 0, plaintextlength);
return plaintext;
}
internal override short KeyExchangeAlgorithm
{
get { return this.keyExchange; }
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>A generic class for ciphersuites in TLS 1.0.</remarks>
public abstract class TlsCipherSuite
{
internal const short KE_RSA = 1;
internal const short KE_RSA_EXPORT = 2;
internal const short KE_DHE_DSS = 3;
internal const short KE_DHE_DSS_EXPORT = 4;
internal const short KE_DHE_RSA = 5;
internal const short KE_DHE_RSA_EXPORT = 6;
internal const short KE_DH_DSS = 7;
internal const short KE_DH_RSA = 8;
internal const short KE_DH_anon = 9;
internal abstract void Init(byte[] ms, byte[] cr, byte[] sr);
internal abstract byte[] EncodePlaintext(short type, byte[] plaintext, int offset, int len);
internal abstract byte[] DecodeCiphertext(short type, byte[] plaintext, int offset, int len, TlsProtocolHandler handler);
internal abstract short KeyExchangeAlgorithm { get; }
}
}

View File

@@ -0,0 +1,72 @@
using System;
using System.IO;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>
/// A manager for ciphersuite. This class does manage all ciphersuites
/// which are used by MicroTLS.
/// </remarks>
public class TlsCipherSuiteManager
{
private const int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000a;
private const int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
private const int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002f;
private const int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
private const int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
private const int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
internal static void WriteCipherSuites(
Stream outStr)
{
TlsUtilities.WriteUint16(2 * 6, outStr);
TlsUtilities.WriteUint16(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_RSA_WITH_AES_256_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_RSA_WITH_AES_128_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_RSA_WITH_3DES_EDE_CBC_SHA, outStr);
}
internal static TlsCipherSuite GetCipherSuite(
int number,
TlsProtocolHandler handler)
{
switch (number)
{
case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new DesEdeEngine()), new CbcBlockCipher(new DesEdeEngine()), new Sha1Digest(), new Sha1Digest(), 24, TlsCipherSuite.KE_RSA);
case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new DesEdeEngine()), new CbcBlockCipher(new DesEdeEngine()), new Sha1Digest(), new Sha1Digest(), 24, TlsCipherSuite.KE_DHE_RSA);
case TLS_RSA_WITH_AES_128_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 16, TlsCipherSuite.KE_RSA);
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 16, TlsCipherSuite.KE_DHE_RSA);
case TLS_RSA_WITH_AES_256_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 32, TlsCipherSuite.KE_RSA);
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 32, TlsCipherSuite.KE_DHE_RSA);
default:
handler.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_handshake_failure);
/*
* Unreachable Code, failWithError will always throw an exception!
*/
return null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
namespace Org.BouncyCastle.Crypto.Tls
{
public class TlsException : Exception
{
public TlsException() : base() { }
public TlsException(string message) : base(message) { }
public TlsException(string message, Exception exception) : base(message, exception) { }
}
}

View File

@@ -0,0 +1,42 @@
using System;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>An input Stream for a TLS 1.0 connection.</remarks>
// TODO Fix name and make internal once TlsProtocolHandler.TlsInputStream is removed
public class TlsInputStream
: BaseInputStream
{
private readonly TlsProtocolHandler handler;
internal TlsInputStream(
TlsProtocolHandler handler)
{
this.handler = handler;
}
public override int Read(
byte[] buf,
int offset,
int len)
{
return this.handler.ReadApplicationData(buf, offset, len);
}
public override int ReadByte()
{
byte[] buf = new byte[1];
if (this.Read(buf, 0, 1) <= 0)
return -1;
return buf[0];
}
public override void Close()
{
handler.Close();
base.Close();
}
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.IO;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Parameters;
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
{
private long seqNo;
private 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.
*/
internal TlsMac(
IDigest digest,
byte[] key_block,
int offset,
int len)
{
this.mac = new HMac(digest);
KeyParameter param = new KeyParameter(key_block, offset, len);
this.mac.Init(param);
this.seqNo = 0;
}
/**
* @return The Keysize of the mac.
*/
internal 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.
*/
internal byte[] CalculateMac(
short type,
byte[] message,
int offset,
int len)
{
try
{
MemoryStream bosMac = new MemoryStream(13 + len);
TlsUtilities.WriteUint64(seqNo++, bosMac);
TlsUtilities.WriteUint8(type, bosMac);
TlsUtilities.WriteVersion(bosMac);
TlsUtilities.WriteUint16(len, bosMac);
bosMac.Write(message, offset, len);
byte[] macData = bosMac.ToArray();
mac.BlockUpdate(macData, 0, macData.Length);
byte[] result = new byte[mac.GetMacSize()];
mac.DoFinal(result, 0);
mac.Reset();
return result;
}
catch (IOException)
{
// This should never happen
throw new InvalidOperationException("Internal error during mac calculation");
}
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>A NULL CipherSuite in java, this should only be used during handshake.</remarks>
public class TlsNullCipherSuite
: TlsCipherSuite
{
internal override void Init(
byte[] ms,
byte[] cr,
byte[] sr)
{
throw new TlsException("Sorry, init of TLS_NULL_WITH_NULL_NULL is forbidden");
}
internal override byte[] EncodePlaintext(
short type,
byte[] plaintext,
int offset,
int len)
{
byte[] result = new byte[len];
Array.Copy(plaintext, offset, result, 0, len);
return result;
}
internal override byte[] DecodeCiphertext(
short type,
byte[] plaintext,
int offset,
int len,
TlsProtocolHandler handler)
{
byte[] result = new byte[len];
Array.Copy(plaintext, offset, result, 0, len);
return result;
}
internal override short KeyExchangeAlgorithm
{
get { return 0; }
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>An output Stream for a TLS 1.0 connection.</remarks>
// TODO Fix name and make internal once TlsProtocolHandler.TlsOuputStream is removed
public class TlsOuputStream
: BaseOutputStream
{
private readonly TlsProtocolHandler handler;
internal TlsOuputStream(
TlsProtocolHandler handler)
{
this.handler = handler;
}
public override void Write(
byte[] buf,
int offset,
int len)
{
this.handler.WriteData(buf, offset, len);
}
[Obsolete("Use version that takes a 'byte' argument")]
public void WriteByte(int arg0)
{
this.Write((byte)arg0);
}
public override void WriteByte(byte b)
{
this.Write(b);
}
public override void Close()
{
handler.Close();
base.Close();
}
public override void Flush()
{
handler.Flush();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,223 @@
using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
/// <remarks>Some helper fuctions for MicroTLS.</remarks>
public class TlsUtilities
{
internal static byte[] ToByteArray(string str)
{
return Strings.ToByteArray(str);
}
internal static void WriteUint8(short i, Stream os)
{
os.WriteByte((byte)i);
}
internal static void WriteUint8(short i, byte[] buf, int offset)
{
buf[offset] = (byte)i;
}
internal static void WriteUint16(int i, Stream os)
{
os.WriteByte((byte)(i >> 8));
os.WriteByte((byte)i);
}
internal static void WriteUint16(int i, byte[] buf, int offset)
{
buf[offset] = (byte)(i >> 8);
buf[offset + 1] = (byte)i;
}
internal static void WriteUint24(int i, Stream os)
{
os.WriteByte((byte)(i >> 16));
os.WriteByte((byte)(i >> 8));
os.WriteByte((byte)i);
}
internal static void WriteUint24(int i, byte[] buf, int offset)
{
buf[offset] = (byte)(i >> 16);
buf[offset + 1] = (byte)(i >> 8);
buf[offset + 2] = (byte)(i);
}
internal static void WriteUint32(long i, Stream os)
{
os.WriteByte((byte)(i >> 24));
os.WriteByte((byte)(i >> 16));
os.WriteByte((byte)(i >> 8));
os.WriteByte((byte)i);
}
internal static void WriteUint32(long i, byte[] buf, int offset)
{
buf[offset] = (byte)(i >> 24);
buf[offset + 1] = (byte)(i >> 16);
buf[offset + 2] = (byte)(i >> 8);
buf[offset + 3] = (byte)(i);
}
internal static void WriteUint64(long i, Stream os)
{
os.WriteByte((byte)(i >> 56));
os.WriteByte((byte)(i >> 48));
os.WriteByte((byte)(i >> 40));
os.WriteByte((byte)(i >> 32));
os.WriteByte((byte)(i >> 24));
os.WriteByte((byte)(i >> 16));
os.WriteByte((byte)(i >> 8));
os.WriteByte((byte)i);
}
internal static void WriteUint64(long i, byte[] buf, int offset)
{
buf[offset] = (byte)(i >> 56);
buf[offset + 1] = (byte)(i >> 48);
buf[offset + 2] = (byte)(i >> 40);
buf[offset + 3] = (byte)(i >> 32);
buf[offset + 4] = (byte)(i >> 24);
buf[offset + 5] = (byte)(i >> 16);
buf[offset + 6] = (byte)(i >> 8);
buf[offset + 7] = (byte)(i);
}
internal static short ReadUint8(Stream inStr)
{
int i = inStr.ReadByte();
if (i < 0)
{
throw new EndOfStreamException();
}
return (short)i;
}
internal static int ReadUint16(Stream inStr)
{
int i1 = inStr.ReadByte();
int i2 = inStr.ReadByte();
if ((i1 | i2) < 0)
{
throw new EndOfStreamException();
}
return i1 << 8 | i2;
}
internal static int ReadUint24(Stream inStr)
{
int i1 = inStr.ReadByte();
int i2 = inStr.ReadByte();
int i3 = inStr.ReadByte();
if ((i1 | i2 | i3) < 0)
{
throw new EndOfStreamException();
}
return (i1 << 16) | (i2 << 8) | i3;
}
internal static long ReadUint32(Stream inStr)
{
int i1 = inStr.ReadByte();
int i2 = inStr.ReadByte();
int i3 = inStr.ReadByte();
int i4 = inStr.ReadByte();
if ((i1 | i2 | i3 | i4) < 0)
{
throw new EndOfStreamException();
}
// TODO Examine this
// return (((long)i1) << 24) | (((long)i2) << 16) | (((long)i3) << 8) | ((long)i4);
return ((long)i1 << 24) | ((long)i2 << 16) | ((long)i3 << 8) | (uint)i4;
}
internal static void ReadFully(byte[] buf, Stream inStr)
{
if (Streams.ReadFully(inStr, buf, 0, buf.Length) < buf.Length)
throw new EndOfStreamException();
}
internal static void CheckVersion(byte[] readVersion, TlsProtocolHandler handler)
{
if ((readVersion[0] != 3) || (readVersion[1] != 1))
{
handler.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_protocol_version);
}
}
internal static void CheckVersion(Stream inStr, TlsProtocolHandler handler)
{
int i1 = inStr.ReadByte();
int i2 = inStr.ReadByte();
if ((i1 != 3) || (i2 != 1))
{
handler.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_protocol_version);
}
}
internal static void WriteVersion(Stream os)
{
os.WriteByte(3);
os.WriteByte(1);
}
private static void hmac_hash(IDigest digest, byte[] secret, byte[] seed, byte[] output)
{
HMac mac = new HMac(digest);
KeyParameter param = new KeyParameter(secret);
byte[] a = seed;
int size = digest.GetDigestSize();
int iterations = (output.Length + size - 1) / size;
byte[] buf = new byte[mac.GetMacSize()];
byte[] buf2 = new byte[mac.GetMacSize()];
for (int i = 0; i < iterations; i++)
{
mac.Init(param);
mac.BlockUpdate(a, 0, a.Length);
mac.DoFinal(buf, 0);
a = buf;
mac.Init(param);
mac.BlockUpdate(a, 0, a.Length);
mac.BlockUpdate(seed, 0, seed.Length);
mac.DoFinal(buf2, 0);
Array.Copy(buf2, 0, output, (size * i), System.Math.Min(size, output.Length - (size * i)));
}
}
internal static void PRF(
byte[] secret,
byte[] label,
byte[] seed,
byte[] buf)
{
int s_half = (secret.Length + 1) / 2;
byte[] s1 = new byte[s_half];
byte[] s2 = new byte[s_half];
Array.Copy(secret, 0, s1, 0, s_half);
Array.Copy(secret, secret.Length - s_half, s2, 0, s_half);
byte[] ls = new byte[label.Length + seed.Length];
Array.Copy(label, 0, ls, 0, label.Length);
Array.Copy(seed, 0, ls, label.Length, seed.Length);
byte[] prf = new byte[buf.Length];
hmac_hash(new MD5Digest(), s1, ls, prf);
hmac_hash(new Sha1Digest(), s2, ls, buf);
for (int i = 0; i < buf.Length; i++)
{
buf[i] ^= prf[i];
}
}
}
}