public CipherSuite GetCipherSuite(ProtocolVersion version, UInt16 id)
{
CipherSuiteInfo cipherSuiteInfo = null;
foreach (CipherSuitePlugin plugin in _plugins) {
List<UInt16> supported = new List<UInt16>(plugin.SupportedCipherSuites);
if (supported.Contains(id)) {
cipherSuiteInfo = plugin.GetCipherSuiteFromID(id);
break;
}
}
if (cipherSuiteInfo == null) {
Console.WriteLine("CipherSuite ID 0x" + id.ToString("x").PadLeft(2, '0') + " not found");
return null;
}
CipherSuite cipherSuite = new CipherSuite(version, id, cipherSuiteInfo.CipherSuiteName);
if (cipherSuiteInfo.KeyExchangeAlgorithmName == null)
cipherSuite.KeyExchangeAlgorithm = new KeyExchangeAlgorithmNull();
if (cipherSuiteInfo.SignatureAlgorithmName == null)
cipherSuite.SignatureAlgorithm = new SignatureAlgorithmNull();
if (cipherSuiteInfo.BulkCipherAlgorithmName == null)
cipherSuite.BulkCipherAlgorithm = new BulkCipherAlgorithmNull();
if (cipherSuiteInfo.MACAlgorithmName == null)
cipherSuite.MACAlgorithm = new MACAlgorithmNull();
// These need to be edited in different versions
string prfName = cipherSuiteInfo.PseudoRandomFunctionName;
string macName = cipherSuiteInfo.MACAlgorithmName;
if (version == ProtocolVersion.SSL3_0) {
if (prfName == null) {
prfName = "SSLv3";
} else {
// PRF selection not supported, but PRF defined, ignore this suite
return null;
}
if (macName == null) {
macName = null;
} else if (macName.Equals("MD5")) {
macName = "SSLv3_MD5";
} else if (macName.Equals("SHA1")) {
macName = "SSLv3_SHA1";
} else {
// Only MD5 and SHA1 MAC accepted in SSLv3, ignore this suite
return null;
}
} else {
if (version.HasSelectablePRF) {
if (prfName == null) {
prfName = "TLS_SHA256";
}
} else {
if (prfName == null) {
prfName = "TLSv1";
} else {
// PRF selection not supported, but PRF defined, ignore this suite
return null;
}
}
}
foreach (CipherSuitePlugin plugin in _plugins) {
if (cipherSuite.KeyExchangeAlgorithm == null) {
cipherSuite.KeyExchangeAlgorithm =
plugin.GetKeyExchangeAlgorithm(cipherSuiteInfo.KeyExchangeAlgorithmName);
}
if (cipherSuite.SignatureAlgorithm == null) {
cipherSuite.SignatureAlgorithm =
plugin.GetSignatureAlgorithm(cipherSuiteInfo.SignatureAlgorithmName);
}
if (cipherSuite.PseudoRandomFunction == null) {
cipherSuite.PseudoRandomFunction =
plugin.GetPseudoRandomFunction(prfName);
/* Check that the PRF is valid as per RFC 5246 section 7.4.9 */
if (cipherSuite.PseudoRandomFunction != null && cipherSuite.PseudoRandomFunction.VerifyDataLength < 12) {
Console.WriteLine("Invalid PseudoRandomFunction, verify data less than 12, ignored");
cipherSuite.PseudoRandomFunction = null;
}
}
if (cipherSuite.BulkCipherAlgorithm == null) {
cipherSuite.BulkCipherAlgorithm =
plugin.GetBulkCipherAlgorithm(cipherSuiteInfo.BulkCipherAlgorithmName);
}
if (cipherSuite.MACAlgorithm == null) {
cipherSuite.MACAlgorithm =
plugin.GetMACAlgorithm(macName);
}
}
if (cipherSuite.KeyExchangeAlgorithm == null || !cipherSuite.KeyExchangeAlgorithm.SupportsProtocolVersion(version)) {
Console.WriteLine("KeyExchangeAlgorithm '" + cipherSuiteInfo.KeyExchangeAlgorithmName + "' not found");
return null;
}
if (cipherSuite.SignatureAlgorithm == null || !cipherSuite.SignatureAlgorithm.SupportsProtocolVersion(version)) {
Console.WriteLine("SignatureAlgorithm '" + cipherSuiteInfo.SignatureAlgorithmName + "' not found");
return null;
}
if (cipherSuite.PseudoRandomFunction == null|| !cipherSuite.PseudoRandomFunction.SupportsProtocolVersion(version)) {
Console.WriteLine("PseudoRandomFunction '" + cipherSuiteInfo.PseudoRandomFunctionName + "' not found");
return null;
}
if (cipherSuite.BulkCipherAlgorithm == null || !cipherSuite.BulkCipherAlgorithm.SupportsProtocolVersion(version)) {
Console.WriteLine("BulkCipherAlgorithm '" + cipherSuiteInfo.BulkCipherAlgorithmName + "' not found");
return null;
}
if (cipherSuite.MACAlgorithm == null || !cipherSuite.MACAlgorithm.SupportsProtocolVersion(version)) {
Console.WriteLine("MACAlgorithm '" + cipherSuiteInfo.MACAlgorithmName + "' not found");
return null;
}
return cipherSuite;
}