Initial commit
This commit is contained in:
commit
5584446828
37 changed files with 7962 additions and 0 deletions
375
TLS/CipherSuites.cs
Normal file
375
TLS/CipherSuites.cs
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
* Secucore
|
||||
*
|
||||
* Copyright (C) 2023 Trevor Hall
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license.
|
||||
*
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using SecuCore.Security;
|
||||
|
||||
namespace SecuCore.TLS
|
||||
{
|
||||
public static class CipherSuites
|
||||
{
|
||||
public enum ConnectionEnd
|
||||
{
|
||||
SERVER,
|
||||
CLIENT
|
||||
}
|
||||
public enum PRFAlgorithm
|
||||
{
|
||||
LEGACY,
|
||||
TLS_PRF_SHA256,
|
||||
TLS_PRF_SHA384
|
||||
}
|
||||
public enum KeyExchangeAlgorithm
|
||||
{
|
||||
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,
|
||||
//RFC 4279
|
||||
PSK,
|
||||
DHE_PSK,
|
||||
RSA_PSK,
|
||||
//RFC 4429
|
||||
ECDH_ECDSA,
|
||||
ECDHE_ECDSA,
|
||||
ECDH_RSA,
|
||||
ECDHE_RSA,
|
||||
ECDH_anon,
|
||||
//RFC 5054
|
||||
SRP,
|
||||
SRP_DSS,
|
||||
SRP_RSA,
|
||||
//RFC 5489
|
||||
ECDHE_PSK
|
||||
}
|
||||
public enum BulkCipherAlgorithm
|
||||
{
|
||||
NULL,
|
||||
RC4,
|
||||
RC2,
|
||||
DES,
|
||||
_3DES,
|
||||
DES40,
|
||||
AES,
|
||||
IDEA
|
||||
}
|
||||
public enum CipherType
|
||||
{
|
||||
STREAM,
|
||||
BLOCK,
|
||||
AEAD
|
||||
}
|
||||
public enum MACAlgorithm
|
||||
{
|
||||
NULL,
|
||||
MD5,
|
||||
SHA,
|
||||
HMAC_MD5 = MD5,
|
||||
HMAC_SHA1 = SHA,
|
||||
HMAC_SHA256,
|
||||
HMAC_SHA384,
|
||||
HMAC_SHA512
|
||||
}
|
||||
public enum CompressionMethod
|
||||
{
|
||||
NULL,
|
||||
DEFLATE
|
||||
}
|
||||
|
||||
public class SecurityParameters
|
||||
{
|
||||
public ConnectionEnd entity;
|
||||
public BulkCipherAlgorithm bulk_cipher_algorithm;
|
||||
public CipherType cipher_type;
|
||||
public byte key_size;
|
||||
public CompressionMethod compression_algorithm;
|
||||
public byte[] master_secret;
|
||||
public byte[] client_random;
|
||||
public byte[] server_random;
|
||||
}
|
||||
|
||||
public enum BulkAlgorithmType
|
||||
{
|
||||
Stream,
|
||||
Block,
|
||||
AEAD
|
||||
}
|
||||
|
||||
public class TLSEncryptionProvider
|
||||
{
|
||||
public TLSCipherSuite tcs;
|
||||
public BulkAlgorithmType bulkAlgorithmType;
|
||||
public int AuthenticationTagSize;
|
||||
public int HashSize;
|
||||
public int IVSize;
|
||||
public int BlockSize;
|
||||
public KeyedHashAlgorithm LocalHasher;
|
||||
public KeyedHashAlgorithm RemoteHasher;
|
||||
public ICryptoTransform Encryptor;
|
||||
public ICryptoTransform Decryptor;
|
||||
|
||||
private void DisposeIfExists(IDisposable d)
|
||||
{
|
||||
if (d != null) d.Dispose();
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeIfExists(Decryptor);
|
||||
DisposeIfExists(Encryptor);
|
||||
DisposeIfExists(LocalHasher);
|
||||
DisposeIfExists(RemoteHasher);
|
||||
}
|
||||
}
|
||||
|
||||
public class TLSCipherImplementation
|
||||
{
|
||||
public Func<SymmetricAlgorithm> getBulkFunc;
|
||||
public Func<HashAlgorithm> getHashFunc;
|
||||
public Func<byte[], HMAC> createHMACFunc;
|
||||
public Func<byte[], byte[], X509Cert, bool> verifyHashFunc;
|
||||
public TLSCipherImplementation(Func<SymmetricAlgorithm> _getBulkFunction, Func<HashAlgorithm> _getHashFunction, Func<byte[], HMAC> _createHMACFunc, Func<byte[], byte[], X509Cert, bool> _verifyHashFunc)
|
||||
{
|
||||
this.getBulkFunc = _getBulkFunction;
|
||||
this.getHashFunc = _getHashFunction;
|
||||
this.createHMACFunc = _createHMACFunc;
|
||||
this.verifyHashFunc = _verifyHashFunc;
|
||||
}
|
||||
public SymmetricAlgorithm GetBulker() => getBulkFunc.Invoke();
|
||||
public HashAlgorithm GetHasher() => getHashFunc.Invoke();
|
||||
public HMAC CreateHMAC(byte[] key) => createHMACFunc.Invoke(key);
|
||||
public bool VerifyHash(byte[] hash, byte[] sig, X509Cert cert) => verifyHashFunc.Invoke(hash, sig, cert);
|
||||
}
|
||||
|
||||
public struct TLSCipherParameters
|
||||
{
|
||||
public int CipherSuite;
|
||||
public string BulkCipherAlgorithmName;
|
||||
public int BlockSize;
|
||||
public int HashSize;
|
||||
public int BulkKeySize;
|
||||
public int BulkIVSize;
|
||||
public CipherMode cipherMode;
|
||||
public KeyExchangeAlgorithm keyExchangeAlgorithm;
|
||||
}
|
||||
|
||||
public class TLSCipherSuite
|
||||
{
|
||||
public TLSCipherParameters tlsparams;
|
||||
TLSCipherImplementation implementation;
|
||||
public byte[] clWriteKey;
|
||||
public byte[] clWriteMAC;
|
||||
|
||||
public TLSCipherSuite(TLSCipherImplementation impl, TLSCipherParameters _tlsparams)
|
||||
{
|
||||
this.implementation = impl;
|
||||
this.tlsparams = _tlsparams;
|
||||
}
|
||||
|
||||
public SymmetricAlgorithm GetBulker()
|
||||
{
|
||||
SymmetricAlgorithm bulker = implementation.GetBulker();
|
||||
bulker.Mode = tlsparams.cipherMode;
|
||||
bulker.Padding = PaddingMode.None;
|
||||
return bulker;
|
||||
}
|
||||
|
||||
public HashAlgorithm GetHasher() => implementation.GetHasher();
|
||||
public HMAC CreateHMAC(byte[] key) => implementation.CreateHMAC(key);
|
||||
public bool VerifyHash(byte[] hash, byte[] sig, X509Cert cert) => implementation.VerifyHash(hash, sig, cert);
|
||||
public TLSEncryptionProvider InitializeEncryption(KeyDerivation.KeyExpansionResult keyring)
|
||||
{
|
||||
clWriteKey = keyring.clientWriteKey;
|
||||
clWriteMAC = keyring.clientWriteMac;
|
||||
|
||||
SymmetricAlgorithm localBulker = GetBulker();
|
||||
localBulker.Key = keyring.clientWriteKey;
|
||||
|
||||
SymmetricAlgorithm remoteBulker = GetBulker();
|
||||
remoteBulker.Key = keyring.serverWriteKey;
|
||||
KeyedHashAlgorithm localHasher = new HMACSHA1(keyring.clientWriteMac);
|
||||
KeyedHashAlgorithm remoteHasher = new HMACSHA1(keyring.serverWriteMac);
|
||||
return new TLSEncryptionProvider
|
||||
{
|
||||
tcs = this,
|
||||
AuthenticationTagSize = 0,
|
||||
bulkAlgorithmType = BulkAlgorithmType.Block,
|
||||
BlockSize = tlsparams.BlockSize,
|
||||
IVSize = tlsparams.BulkIVSize,
|
||||
HashSize = tlsparams.HashSize,
|
||||
Encryptor = localBulker.CreateEncryptor(),
|
||||
Decryptor = remoteBulker.CreateDecryptor(),
|
||||
LocalHasher = localHasher,
|
||||
RemoteHasher = remoteHasher
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static bool VerifyHashEDCSA(byte[] hash, byte[] sig, X509Cert publicCert)
|
||||
{
|
||||
using (ECDsa ecd = ECDsaCertificateExtensions.GetECDsaPublicKey(new X509Certificate2(publicCert.sourceData)))
|
||||
{
|
||||
bool valid = ecd.VerifyHash(hash, sig, DSASignatureFormat.Rfc3279DerSequence);
|
||||
return valid;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool VerifyHashRSA(byte[] hash, byte[] sig, X509Cert publicCert)
|
||||
{
|
||||
RSAPublicKey rpk = publicCert.GetRSAPublicKey();
|
||||
byte[] decrypted = rpk.DecryptSignature(sig);
|
||||
byte[] actualhash;
|
||||
|
||||
if (decrypted.Length == 36)
|
||||
{
|
||||
actualhash = decrypted;
|
||||
}
|
||||
else
|
||||
{
|
||||
actualhash = Asn1Tools.ParseHash(decrypted);
|
||||
}
|
||||
if (Asn1Tools.HashesEqual(hash, actualhash))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static HashAlgorithm CreateSha1()
|
||||
{
|
||||
return SHA1.Create();
|
||||
}
|
||||
private static HashAlgorithm CreateSha256()
|
||||
{
|
||||
return SHA256.Create();
|
||||
}
|
||||
private static SymmetricAlgorithm CreateAes()
|
||||
{
|
||||
AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider
|
||||
{
|
||||
BlockSize = 128,
|
||||
KeySize = 128,
|
||||
Padding = PaddingMode.None,
|
||||
Mode = CipherMode.CBC,
|
||||
|
||||
};
|
||||
return aesProvider;
|
||||
}
|
||||
private static HMAC CreateSha1Hmac(byte[] key)
|
||||
{
|
||||
return new HMACSHA1(key);
|
||||
}
|
||||
private static HMAC CreateSha256Hmac(byte[] key)
|
||||
{
|
||||
return new HMACSHA256(key);
|
||||
}
|
||||
|
||||
public static ushort[] GetSupportedCipherSuites()
|
||||
{
|
||||
CipherSuiteValue[] cipherSuiteValues = SupportedSuites.Keys.ToList().ToArray();
|
||||
List<ushort> usv = new List<ushort>();
|
||||
foreach (var cipherSuiteValue in cipherSuiteValues) usv.Add((ushort)cipherSuiteValue);
|
||||
return usv.ToArray();
|
||||
}
|
||||
|
||||
public static TLSCipherSuite InitializeCipherSuite(ushort ciphersuitevalue)
|
||||
{
|
||||
CipherSuiteValue key = (CipherSuiteValue)ciphersuitevalue;
|
||||
return SupportedSuites[key].Invoke();
|
||||
}
|
||||
|
||||
public static Dictionary<CipherSuiteValue, Func<TLSCipherSuite>> SupportedSuites = new Dictionary<CipherSuiteValue, Func<TLSCipherSuite>>
|
||||
{
|
||||
//TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
|
||||
{
|
||||
CipherSuiteValue.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
()=>{
|
||||
return
|
||||
new TLSCipherSuite(
|
||||
new TLSCipherImplementation(CreateAes,CreateSha1,CreateSha256Hmac,VerifyHashRSA),
|
||||
new TLSCipherParameters()
|
||||
{
|
||||
BlockSize = 16,
|
||||
BulkCipherAlgorithmName = "AES",
|
||||
BulkIVSize = 16,
|
||||
BulkKeySize = 16,
|
||||
HashSize = 20,
|
||||
cipherMode = CipherMode.CBC,
|
||||
CipherSuite = (int)CipherSuiteValue.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
keyExchangeAlgorithm = KeyExchangeAlgorithm.ECDHE_RSA
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
//TLS_RSA_WITH_AES_128_CBC_SHA
|
||||
{
|
||||
CipherSuiteValue.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
()=>{
|
||||
return
|
||||
new TLSCipherSuite(
|
||||
new TLSCipherImplementation(CreateAes,CreateSha1,CreateSha256Hmac,VerifyHashRSA),
|
||||
new TLSCipherParameters()
|
||||
{
|
||||
BlockSize = 16,
|
||||
BulkCipherAlgorithmName = "AES",
|
||||
BulkIVSize = 16,
|
||||
BulkKeySize = 16,
|
||||
HashSize = 20,
|
||||
cipherMode = CipherMode.CBC,
|
||||
CipherSuite = (int)CipherSuiteValue.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
keyExchangeAlgorithm = KeyExchangeAlgorithm.RSA
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
CipherSuiteValue.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
()=>{
|
||||
return
|
||||
new TLSCipherSuite(
|
||||
new TLSCipherImplementation(CreateAes,CreateSha1,CreateSha256Hmac,VerifyHashEDCSA),
|
||||
new TLSCipherParameters()
|
||||
{
|
||||
BlockSize = 16,
|
||||
BulkCipherAlgorithmName = "AES",
|
||||
BulkIVSize = 16,
|
||||
BulkKeySize = 16,
|
||||
HashSize = 20,
|
||||
cipherMode = CipherMode.CBC,
|
||||
CipherSuite = (int)CipherSuiteValue.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
keyExchangeAlgorithm = KeyExchangeAlgorithm.ECDHE_ECDSA
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public enum CipherSuiteValue
|
||||
{
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA = 47,
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 49171,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 49161
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue