public HandshakeCertificateRequest(ProtocolVersion version) : base(HandshakeMessageType.CertificateRequest, version) { CertificateTypes = new List<byte>(); SignatureAndHashAlgorithms = new List<ushort>(); CertificateAuthorities = new List<string>(); }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { if (!(publicKey.Algorithm is RSACryptoServiceProvider)) { throw new CryptographicException("RSA key exchange requires RSA public key"); } return GetClientKeys(version, clientVersion, (RSACryptoServiceProvider)publicKey.Algorithm); }
public override bool SupportsProtocolVersion(ProtocolVersion version) { if (version == ProtocolVersion.TLS1_0 || version == ProtocolVersion.TLS1_1 || version == ProtocolVersion.DTLS1_0) { return true; } return false; }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { byte[] ecPoint = Blob2Point(_ecdhCng.PublicKey.ToByteArray()); byte[] ret = new byte[1+ecPoint.Length]; ret[0] = (byte) (ecPoint.Length); Buffer.BlockCopy(ecPoint, 0, ret, 1, ecPoint.Length); return ret; }
public HandshakeClientHello(ProtocolVersion version) : base(HandshakeMessageType.ClientHello, version) { ClientVersion = version; Random = new HandshakeRandom(); SessionID = new byte[0]; Cookie = new byte[0]; CipherSuites = new List<UInt16>(); CompressionMethods = new List<Byte>(); Extensions = new List<HelloExtension>(); }
public HandshakeMessage(HandshakeMessageType type, ProtocolVersion version, byte[] data) { if (data == null) { throw new AlertException(AlertDescription.InternalError, "Trying to create HandshakeMessage with null data"); } Type = type; _version = version; _data = (byte[])data.Clone(); }
public CipherSuite(ProtocolVersion version) { ProtocolVersion = version; CipherSuiteID = 0x0000; CipherSuiteName = "TLS_NULL_WITH_NULL_NULL"; _keyExchangeAlgorithm = new KeyExchangeAlgorithmNull(); _signatureAlgorithm = new SignatureAlgorithmNull(); _pseudoRandomFunction = null; _bulkCipherAlgorithm = new BulkCipherAlgorithmNull(); _macAlgorithm = new MACAlgorithmNull(); }
public override void ProcessClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePrivateKey privateKey, byte[] data) { if (data[0] != data.Length-1) { throw new Exception("Incorrect ECPoint length"); } // Exctract the ECPoint byte[] ecPoint = new byte[data.Length-1]; Buffer.BlockCopy(data, 1, ecPoint, 0, ecPoint.Length); // Create key blob and public key byte[] keyBlob = Point2Blob(ecPoint); _publicKey = ECDiffieHellmanCngPublicKey.FromByteArray(keyBlob, CngKeyBlobFormat.EccPublicBlob); }
public static HandshakeMessage GetInstance(ProtocolVersion version, byte[] data) { HandshakeMessage ret = null; switch ((HandshakeMessageType) data[0]) { case HandshakeMessageType.HelloRequest: ret = new HandshakeMessage(HandshakeMessageType.HelloRequest, version); break; case HandshakeMessageType.ClientHello: ret = new HandshakeClientHello(); break; case HandshakeMessageType.ServerHello: ret = new HandshakeServerHello(); break; case HandshakeMessageType.HelloVerifyRequest: ret = new HandshakeMessage(HandshakeMessageType.HelloVerifyRequest, version); break; case HandshakeMessageType.NewSessionTicket: ret = new HandshakeMessage(HandshakeMessageType.NewSessionTicket, version); break; case HandshakeMessageType.Certificate: ret = new HandshakeCertificate(version); break; case HandshakeMessageType.ServerKeyExchange: ret = new HandshakeMessage(HandshakeMessageType.ServerKeyExchange, version); break; case HandshakeMessageType.CertificateRequest: ret = new HandshakeCertificateRequest(version); break; case HandshakeMessageType.ServerHelloDone: ret = new HandshakeMessage(HandshakeMessageType.ServerHelloDone, version); break; case HandshakeMessageType.CertificateVerify: ret = new HandshakeMessage(HandshakeMessageType.CertificateVerify, version); break; case HandshakeMessageType.ClientKeyExchange: ret = new HandshakeMessage(HandshakeMessageType.ClientKeyExchange, version); break; case HandshakeMessageType.Finished: ret = new HandshakeMessage(HandshakeMessageType.Finished, version); break; } if (ret != null) { ret.Decode(data); return ret; } return null; }
public override byte[] GetServerKeys(ProtocolVersion version) { _ecdhCng = new ECDiffieHellmanCng(256); UInt16 namedCurve = KeySizeToNamedCurve(256); byte[] ecPoint = Blob2Point(_ecdhCng.PublicKey.ToByteArray()); byte[] ret = new byte[4+ecPoint.Length]; ret[0] = 3; // ECCurveType.named_curve ret[1] = (byte) (namedCurve >> 8); ret[2] = (byte) (namedCurve); ret[3] = (byte) (ecPoint.Length); Buffer.BlockCopy(ecPoint, 0, ret, 4, ecPoint.Length); return ret; }
public RecordHandler(ProtocolVersion version, bool isClient) { _isClient = isClient; // Start with NULL cipher suite and key block _nextCipherSuite = new CipherSuite(version); _nextKeyBlock = new KeyBlock(); // Initialize all the other variables ChangeLocalState(); ChangeRemoteState(); _inputEpoch = 0; _outputEpoch = 0; }
public override byte[] SignData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePrivateKey privateKey) { if (hashAlgorithm != null && !(hashAlgorithm is SHA1)) { throw new Exception("DSA signature requires SHA1 hash algorithm"); } if (!(privateKey.Algorithm is DSACryptoServiceProvider)) { throw new Exception("DSA signature requires DSA private key"); } DSACryptoServiceProvider dsaKey = (DSACryptoServiceProvider) privateKey.Algorithm; if (dsaKey.PublicOnly) { throw new Exception("DSA private key required for signing"); } return DEREncodeSignature(dsaKey.SignData(data)); }
protected override void DecodeDataBytes(ProtocolVersion version, byte[] data) { CertificateTypes.Clear(); CertificateAuthorities.Clear(); MemoryStream memStream = new MemoryStream(data); HandshakeStream stream = new HandshakeStream(memStream); int typesLength = stream.ReadUInt8(); for (int i=0; i<typesLength; i++) { CertificateTypes.Add(stream.ReadUInt8()); } if (version.HasSelectableSighash) { int sighashLength = stream.ReadUInt16(); if ((sighashLength%2) != 0) { throw new AlertException(AlertDescription.IllegalParameter, "SianatureAndHashAlgorithms length invalid: " + sighashLength); } byte[] sighashData = stream.ReadBytes(sighashLength); for (int i=0; i<sighashLength; i+=2) { SignatureAndHashAlgorithms.Add((UInt16)((sighashData[i] << 8) | sighashData[i+1])); } } int authsLength = stream.ReadUInt16(); byte[] authData = stream.ReadBytes(authsLength); stream.ConfirmEndOfStream(); int position=0; while (position < authData.Length) { int authLength = (authData[position] << 8) | authData[position+1]; position += 2; if (position > authData.Length) { throw new AlertException(AlertDescription.IllegalParameter, "Authorities total length doesn't match contents"); } string name = Encoding.ASCII.GetString(authData, position, authLength); position += authLength; CertificateAuthorities.Add(name); } }
protected override byte[] EncodeDataBytes(ProtocolVersion version) { int certsLength = 0; foreach (X509Certificate cert in CertificateList) { certsLength += 3; certsLength += cert.GetRawCertData().Length; } MemoryStream memStream = new MemoryStream(); HandshakeStream stream = new HandshakeStream(memStream); stream.WriteUInt24((UInt32) certsLength); foreach (X509Certificate cert in CertificateList) { byte[] certBytes = cert.GetRawCertData(); stream.WriteUInt24((UInt32) certBytes.Length); stream.WriteBytes(certBytes); } return memStream.ToArray(); }
protected override void DecodeDataBytes(ProtocolVersion version, byte[] data) { CertificateList.Clear(); MemoryStream memStream = new MemoryStream(data); HandshakeStream stream = new HandshakeStream(memStream); int certsLength = (int) stream.ReadUInt24(); int readBytes = 0; while (readBytes<certsLength) { int certLength = (int) stream.ReadUInt24(); byte[] certBytes = stream.ReadBytes(certLength); readBytes += 3+certLength; CertificateList.Add(new X509Certificate(certBytes)); } if (readBytes != certsLength) { throw new AlertException(AlertDescription.IllegalParameter, "Certificate total length doesn't match contents"); } stream.ConfirmEndOfStream(); }
public byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, RSACryptoServiceProvider rsa) { _preMasterSecret = new byte[48]; RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider(); rngCsp.GetBytes(_preMasterSecret); _preMasterSecret[0] = clientVersion.Major; _preMasterSecret[1] = clientVersion.Minor; byte[] encryptedBytes = rsa.Encrypt(_preMasterSecret, false); byte[] ret; if (version != ProtocolVersion.SSL3_0) { // TLS 1.0 and later require a useless vector length ret = new byte[2+encryptedBytes.Length]; ret[0] = (byte) (encryptedBytes.Length >> 8); ret[1] = (byte) (encryptedBytes.Length); Buffer.BlockCopy(encryptedBytes, 0, ret, 2, encryptedBytes.Length); } else { ret = encryptedBytes; } return ret; }
public virtual bool SupportsProtocolVersion(ProtocolVersion version) { return version.HasExtensions; }
public HandshakeCertificate(ProtocolVersion version) : base(HandshakeMessageType.Certificate, version) { CertificateList = new X509CertificateCollection(); }
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); }
// Returns true if this version is supported, otherwise false public abstract bool SupportsProtocolVersion(ProtocolVersion version);
public HandshakeMessage(HandshakeMessageType type, ProtocolVersion version) { Type = type; _version = version; _data = new byte[0]; }
protected virtual byte[] EncodeDataBytes(ProtocolVersion version) { return _data; }
protected virtual void DecodeDataBytes(ProtocolVersion version, byte[] data) { _data = data; }
public override bool SupportsProtocolVersion(ProtocolVersion version) { return true; }
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (hashAlgorithm != null && !(hashAlgorithm is SHA1)) { throw new Exception("DSA signature verification requires SHA1 hash algorithm"); } if (!CertificateKeyAlgorithm.Equals(publicKey.Oid) || !(publicKey.Algorithm is DSACryptoServiceProvider)) { throw new Exception("DSA signature verification requires DSA public key"); } return VerifyData(data, (DSACryptoServiceProvider)publicKey.Algorithm, signature); }
protected HandshakeSession(SecurityParameters securityParameters) { string path = System.Reflection.Assembly.GetAssembly(typeof(HandshakeSession)).Location; string directory = Path.GetDirectoryName(path); _pluginManager = new CipherSuitePluginManager(directory); _state = HandshakeState.Initial; _minVersion = securityParameters.MinimumVersion; _maxVersion = securityParameters.MaximumVersion; _supportedCipherSuites = securityParameters.CipherSuiteIDs.ToArray(); _supportedCompressions = securityParameters.CompressionIDs.ToArray(); _availableCertificates = new List<X509CertificateCollection>(securityParameters.AvailableCertificates); _availablePrivateKeys = new List<CertificatePrivateKey>(securityParameters.AvailablePrivateKeys); _clientCertificates = new X509CertificateCollection(); _serverCertificates = new X509CertificateCollection(); // Initialize the default ClientHello version, to // be as compatible as possible based on maxVersion if (_maxVersion == ProtocolVersion.SSL3_0) { _version = ProtocolVersion.SSL3_0; } else if (_maxVersion.IsUsingDatagrams) { _version = ProtocolVersion.DTLS1_0; } else { _version = ProtocolVersion.TLS1_0; } _cipherSuite = new CipherSuite(_version); }
protected static byte[] GenerateMasterSecret(ProtocolVersion version, CipherSuite cipherSuite, ConnectionState connectionState) { byte[] seed = new byte[64]; Array.Copy(connectionState.ClientRandom, 0, seed, 0, 32); Array.Copy(connectionState.ServerRandom, 0, seed, 32, 32); byte[] masterSecret = cipherSuite.KeyExchangeAlgorithm.GetMasterSecret(cipherSuite.PseudoRandomFunction, seed); if (masterSecret == null) { throw new Exception("Could not generate master secret"); } return masterSecret; }
protected override void DecodeDataBytes(ProtocolVersion ver, byte[] data) { CipherSuites.Clear(); CompressionMethods.Clear(); MemoryStream memStream = new MemoryStream(data); HandshakeStream stream = new HandshakeStream(memStream); byte major = stream.ReadUInt8(); byte minor = stream.ReadUInt8(); ClientVersion = new ProtocolVersion(major, minor); byte[] randomBytes = stream.ReadBytes(32); Random = new HandshakeRandom(randomBytes); int idLength = (int) stream.ReadUInt8(); SessionID = stream.ReadBytes(idLength); if (ClientVersion.IsUsingDatagrams) { int cookieLength = (int) stream.ReadUInt8(); Cookie = stream.ReadBytes(cookieLength); } int cipherLength = (int) stream.ReadUInt16(); for (int i=0; i<cipherLength; i+=2) { CipherSuites.Add(stream.ReadUInt16()); } int compressionLength = (int) stream.ReadUInt8(); for (int i=0; i<compressionLength; i++) { CompressionMethods.Add(stream.ReadUInt8()); } byte[] extensionList = new byte[0]; if (!stream.EndOfStream && ClientVersion.HasExtensions) { UInt16 extensionListLength = stream.ReadUInt16(); extensionList = stream.ReadBytes(extensionListLength); } stream.ConfirmEndOfStream(); int pos = 0; while (pos+4 <= extensionList.Length) { UInt16 extensionType = (UInt16) ((extensionList[pos] << 8) | extensionList[pos+1]); UInt16 extensionDataLength = (UInt16) ((extensionList[pos+2] << 8) | extensionList[pos+3]); pos += 4; if (pos+extensionDataLength > extensionList.Length) { throw new AlertException(AlertDescription.IllegalParameter, "ClientHello extension data length too large: " + extensionDataLength); } byte[] extensionData = new byte[extensionDataLength]; Buffer.BlockCopy(extensionList, pos, extensionData, 0, extensionData.Length); pos += extensionData.Length; Extensions.Add(new HelloExtension(extensionType, extensionData)); } }
public HandshakeHelloVerifyRequest(ProtocolVersion version) : base(HandshakeMessageType.HelloVerifyRequest, version) { ServerVersion = version; Cookie = new byte[0]; }
public override bool SupportsProtocolVersion(ProtocolVersion version) { return (version == ProtocolVersion.SSL3_0); }
public override bool SupportsProtocolVersion(ProtocolVersion version) { return version.HasSelectablePRF; }