public override void SetFromNetMQMessage(NetMQMessage message) { base.SetFromNetMQMessage(message); if (message.FrameCount != 3) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidFramesCount, "Malformed message"); } // get the randon number NetMQFrame randomNumberFrame = message.Pop(); RandomNumber = randomNumberFrame.ToByteArray(); // get the length of the ciphers array NetMQFrame ciphersLengthFrame = message.Pop(); int ciphersLength = BitConverter.ToInt32(ciphersLengthFrame.Buffer, 0); // get the ciphers NetMQFrame ciphersFrame = message.Pop(); CipherSuites = new CipherSuite[ciphersLength]; for (int i = 0; i < ciphersLength; i++) { CipherSuites[i] = (CipherSuite)ciphersFrame.Buffer[i * 2 + 1]; } }
public CipherSuite DecideCipherSuite(CipherSuite[] clientCipherSuites) { var supportedCiphers = CipherSuiteExtensions.GetSupportedCipherSuites(); var cipher = clientCipherSuites.FirstOrDefault(x => supportedCiphers.Contains(x)); // WARNING: default is TLS_NULL_WITH_NULL_NULL.... return cipher; }
public ServerHello(ProtocolVersion ver, byte[] random, byte[] sessionID, CipherSuite suite, CompressionMethod compression, Extension[] extensions) : base(HandshakeType.ServerHello) { _version = ver; _random = random; _sessionID = sessionID; _cipherSuite = suite; _compression = compression; _extensions = extensions; }
public ClientHelloMessage(TlsVersion version, byte[] randomBytes, byte[] sessionId, HelloExtension[] extensions, CipherSuite[] cipherSuites, CompressionMethod[] compressionMethods) : base(HandshakeType.ClientHello, version, randomBytes, sessionId, extensions) { SecurityAssert.NotNull(cipherSuites); SecurityAssert.SAssert(cipherSuites.Length >= 2 && cipherSuites.Length <= 0xFFFE); CipherSuites = cipherSuites; SecurityAssert.NotNull(compressionMethods); SecurityAssert.SAssert(compressionMethods.Length >= 1 && cipherSuites.Length <= 0xFF); CompressionMethods = compressionMethods; }
/// <summary> /// Remove the three frames from the given NetMQMessage, interpreting them thusly: /// 1. a byte with the <see cref="HandshakeType"/>, /// 2. RandomNumber (a byte-array), /// 3. a 2-byte array with the <see cref="CipherSuite"/> in the 2nd byte. /// </summary> /// <param name="message">a NetMQMessage - which must have 3 frames</param> /// <exception cref="NetMQSecurityException"><see cref="NetMQSecurityErrorCode.InvalidFramesCount"/>: FrameCount must be 2.</exception> public override void SetFromNetMQMessage(NetMQMessage message) { base.SetFromNetMQMessage(message); if (message.FrameCount != 2) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidFramesCount, "Malformed message"); } // Get the random number NetMQFrame randomNumberFrame = message.Pop(); RandomNumber = randomNumberFrame.ToByteArray(); // Get the cipher suite NetMQFrame cipherSuiteFrame = message.Pop(); CipherSuite = (CipherSuite)cipherSuiteFrame.Buffer[1]; }
public virtual CipherSuite Select(CipherSuite[] suites) { CipherSuite[] supports = _supports; int minIdx = int.MaxValue; for (int q = 0; q < suites.Length; q ++) { for (int i = 0; i < supports.Length; i++) { if (suites[q] == supports[i]) { if (minIdx > i) minIdx = i; break; } } } if (minIdx == int.MaxValue) return CipherSuite.NONE; return supports[minIdx]; }
public HandshakeLayer(SecureChannel secureChannel, ConnectionEnd connectionEnd) { m_secureChannel = secureChannel; SecurityParameters = new SecurityParameters(); SecurityParameters.Entity = connectionEnd; SecurityParameters.CompressionAlgorithm = CompressionMethod.Null; SecurityParameters.PRFAlgorithm = PRFAlgorithm.SHA256; SecurityParameters.CipherType = CipherType.Block; AllowedCipherSuites = new CipherSuite[] { CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256, CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, }; VerifyCertificate = c => c.Verify(); }
public void SSLv3Test() { byte[] finished1eb = new byte[] { 0x16, 0x03, 0x00, 0x00, 0x40, 0x3c, 0xcd, 0xad, 0xec, 0xd6, 0x18, 0x75, 0x2e, 0x6e, 0x37, 0xdf, 0x19, 0x6d, 0x4f, 0xd4, 0x9c, 0x2c, 0x42, 0x1c, 0xe7, 0x74, 0x45, 0xf9, 0x77, 0xb1, 0xde, 0x79, 0x0f, 0xc4, 0x8b, 0xaf, 0x85, 0x7b, 0xa3, 0x73, 0x92, 0x4c, 0xb7, 0xf4, 0xa3, 0x45, 0x78, 0x53, 0x88, 0x18, 0xff, 0x2f, 0x3f, 0x7d, 0x27, 0xa1, 0x4c, 0xa4, 0x1a, 0x5d, 0x81, 0x8d, 0xf3, 0xc8, 0x3b, 0xb3, 0x71, 0x77, 0x59 }; byte[] finished2eb = new byte[] { 0x16, 0x03, 0x00, 0x00, 0x40, 0xaa, 0xd4, 0x9e, 0x02, 0x07, 0x52, 0x0f, 0xb0, 0x82, 0x79, 0x9a, 0xbe, 0x53, 0xce, 0xfe, 0x66, 0xb3, 0xd5, 0xb1, 0x58, 0x84, 0x5e, 0xe4, 0x7a, 0xb7, 0x86, 0x4c, 0xbe, 0x33, 0x75, 0xc0, 0x57, 0xab, 0x78, 0xba, 0x18, 0x02, 0xa8, 0xcb, 0x26, 0x2b, 0x0d, 0x3e, 0x3a, 0xdb, 0xc5, 0x7a, 0xb8, 0x33, 0x6c, 0x35, 0xe3, 0xa6, 0x09, 0xfe, 0x54, 0x45, 0xd0, 0x66, 0xad, 0x95, 0xff, 0xb0, 0x3c }; byte[] finished1db = new byte[] { 0x16, 0x03, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, 0x24, 0x98, 0x29, 0xF5, 0xAB, 0x95, 0xFD, 0x76, 0x14, 0xDA, 0xA0, 0xA7, 0x97, 0x22, 0xCF, 0xB5, 0x27, 0x8C, 0x96, 0xC6, 0xC7, 0x37, 0xDF, 0xD6, 0x25, 0xB9, 0x19, 0x65, 0x2B, 0xA5, 0x06, 0x7D, 0x10, 0x73, 0x7A, 0x59, 0xEA }; byte[] finished2db = new byte[] { 0x16, 0x03, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, 0x24, 0x34, 0xCC, 0xA5, 0xD0, 0x08, 0x84, 0x26, 0x19, 0xD9, 0xE5, 0x20, 0x68, 0x7B, 0xE5, 0x27, 0xC8, 0x82, 0x71, 0x4E, 0xB1, 0x0E, 0xED, 0xE9, 0x52, 0x01, 0xF3, 0xBE, 0x10, 0x46, 0x52, 0xDE, 0x68, 0x2B, 0x42, 0xF8, 0x5F }; byte[] crandom = new byte[] { 0x4e, 0x60, 0xc6, 0xbd, 0x66, 0xbb, 0x66, 0x74, 0xc8, 0xa2, 0x65, 0x5a, 0x1c, 0x3d, 0xf3, 0x7d, 0xb0, 0xbc, 0x39, 0x60, 0x82, 0x6b, 0xec, 0xe9, 0x62, 0xc6, 0xaa, 0x92, 0x5f, 0x7c, 0x3d, 0x3a }; byte[] srandom = new byte[] { 0x4e, 0x60, 0xc6, 0xb9, 0x1f, 0xff, 0xb5, 0x62, 0xad, 0x3b, 0xe9, 0x16, 0xd9, 0x80, 0x04, 0xc5, 0x91, 0x92, 0xa7, 0x1b, 0xe1, 0x39, 0x9e, 0x91, 0x16, 0x76, 0xe1, 0x71, 0x2a, 0x9e, 0x23, 0x62 }; byte[] master = new byte[] { 0x7C, 0xEE, 0xFE, 0xE3, 0x6A, 0x10, 0x82, 0xDC, 0x69, 0xB0, 0xF2, 0x7C, 0xB6, 0xC1, 0xE9, 0x93, 0xD8, 0x53, 0x40, 0x52, 0x7F, 0xAB, 0x2A, 0x45, 0x3B, 0x4D, 0x69, 0xEF, 0x67, 0x60, 0xC2, 0x0E, 0x97, 0x23, 0x40, 0x2B, 0x5A, 0x99, 0x90, 0x06, 0xA7, 0x13, 0x10, 0x47, 0x5A, 0xC7, 0x6A, 0xAA }; Record finished1 = GetRecord(finished1db); Record finished2 = GetRecord(finished2eb); CipherSuitePluginManager pluginManager = GetPluginManager(); RecordHandler recordHandler = new RecordHandler(ProtocolVersion.SSL3_0, true); CipherSuite cipherSuite = pluginManager.GetCipherSuite(ProtocolVersion.SSL3_0, 0x000a); Assert.IsNotNull(cipherSuite); // Set correct cipher suite ConnectionState connectionState = new ConnectionState(crandom, srandom, master); recordHandler.SetCipherSuite(cipherSuite, connectionState); // Test that initial state doesn't modify records recordHandler.ProcessOutputRecord(finished1); recordHandler.ProcessInputRecord(finished2); Assert.AreEqual(finished1db, finished1.GetBytes()); Assert.AreEqual(finished2eb, finished2.GetBytes()); recordHandler.ChangeLocalState(); recordHandler.ProcessOutputRecord(finished1); recordHandler.ChangeRemoteState(); recordHandler.ProcessInputRecord(finished2); // Ignore last block, it has some random padding int bsize = cipherSuite.BulkCipherAlgorithm.BlockSize; byte[] tmp1 = new byte[finished1eb.Length - bsize]; byte[] tmp2 = new byte[finished1eb.Length - bsize]; Buffer.BlockCopy(finished1eb, 0, tmp1, 0, tmp1.Length); Buffer.BlockCopy(finished1.GetBytes(), 0, tmp2, 0, tmp2.Length); Assert.AreEqual(tmp1, tmp2); Assert.AreEqual(finished2db, finished2.GetBytes()); }
private void SetCipherSuite(CipherSuite cipher) { switch (cipher) { case CipherSuite.TLS_NULL_WITH_NULL_NULL: case CipherSuite.TLS_RSA_WITH_NULL_SHA: case CipherSuite.TLS_RSA_WITH_NULL_SHA256: SecurityParameters.BulkCipherAlgorithm = BulkCipherAlgorithm.Null; SecurityParameters.FixedIVLength = 0; SecurityParameters.EncKeyLength = 0; SecurityParameters.BlockLength = 0; SecurityParameters.RecordIVLength = 0; break; case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: SecurityParameters.BulkCipherAlgorithm = BulkCipherAlgorithm.AES; SecurityParameters.FixedIVLength = 0; SecurityParameters.EncKeyLength = 16; SecurityParameters.BlockLength = 16; SecurityParameters.RecordIVLength = 16; break; case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: SecurityParameters.BulkCipherAlgorithm = BulkCipherAlgorithm.AES; SecurityParameters.FixedIVLength = 0; SecurityParameters.EncKeyLength = 32; SecurityParameters.BlockLength = 16; SecurityParameters.RecordIVLength = 16; break; default: throw new ArgumentOutOfRangeException("cipher"); } switch (cipher) { case CipherSuite.TLS_NULL_WITH_NULL_NULL: SecurityParameters.MACAlgorithm = MACAlgorithm.Null; SecurityParameters.MACKeyLength = 0; SecurityParameters.MACLength = 0; break; case CipherSuite.TLS_RSA_WITH_NULL_SHA: case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: SecurityParameters.MACAlgorithm = MACAlgorithm.HMACSha1; SecurityParameters.MACKeyLength = 20; SecurityParameters.MACLength = 20; break; case CipherSuite.TLS_RSA_WITH_NULL_SHA256: case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: SecurityParameters.MACAlgorithm = MACAlgorithm.HMACSha256; SecurityParameters.MACKeyLength = 32; SecurityParameters.MACLength = 32; break; default: throw new ArgumentOutOfRangeException("cipher"); } }
public static bool IsAEADCipher(this ICipherSuitesProvider cipherSuiteProvider, CipherSuite cipherSuite) { var cipherAlgorithm = cipherSuiteProvider.ResolveCipherAlgorithm(cipherSuite); return(cipherAlgorithm is AEADCipherAdapter || cipherAlgorithm is IAEADBlockCipher); }
public override string ToString() { return(CipherSuite.ToString()); }
public IActionResult IssueCertificate(CertRequest certRequest) { if (certRequest.CertPassphrase.Length < Constants.MinPassphraseLength) { _logger.LogWarning( string.Format( "User {} tried to issue new certificate with too short passphrase.", certRequest.Uid ) ); return(BadRequest("Too short passphrase")); } CipherSuite cipherSuite = certRequest.RequestedCipherSuite; if (!cipherSuite.IsValidCipherSuite()) { _logger.LogWarning("Invalid cipher suite:\n" + cipherSuite); return(BadRequest("Invalid cipher suite.")); } User user = _userDBAuthenticator.AuthenticateAndGetUser(certRequest.Uid, certRequest.Password); if (user != null) { // Load the certificate X509Certificate2 coreCACert = new X509Certificate2(CAConfig.CoreCACertPath); HashAlgorithmName hashAlg = new HashAlgorithmName(cipherSuite.HashAlg); AsymmetricAlgorithm privKey = null; string privKeyExport = null; CertificateRequest req = null; if (cipherSuite.Alg.Equals(EncryptionAlgorithms.RSA)) { privKey = RSA.Create(cipherSuite.KeySize); privKeyExport = ((RSA)privKey).ToPem(); req = new CertificateRequest( "CN=" + user.Id, (RSA)privKey, hashAlg, RSASignaturePadding.Pss ); } else if (cipherSuite.Alg.Equals(EncryptionAlgorithms.ECDSA)) { privKey = ECDsa.Create(); privKeyExport = ((ECDsa)privKey).ToPem(); req = new CertificateRequest( "CN=" + user.Id, (ECDsa)privKey, hashAlg ); } else { _logger.LogError( string.Format( "Unknown encryption algorithm '{0}'.", cipherSuite.Alg ) ); throw new CryptographicUnexpectedOperationException(); } // Add email as SAN SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); sanBuilder.AddEmailAddress(user.Email); req.CertificateExtensions.Add(sanBuilder.Build()); // Arguments: Is no CA, no restricted nr of path levels, (nr of path levels), is not critical req.CertificateExtensions.Add( new X509BasicConstraintsExtension(false, false, 0, false) ); req.CertificateExtensions.Add( new X509SubjectKeyIdentifierExtension(req.PublicKey, false) ); req.CertificateExtensions.Add( new X509KeyUsageExtension( X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation, false ) ); OidCollection oidCollection = new OidCollection(); // Set Client Authentication Oid oidCollection.Add(new Oid("1.3.6.1.5.5.7.3.2")); // Set Secure Email / Email protection Oid oidCollection.Add(new Oid("1.3.6.1.5.5.7.3.4")); req.CertificateExtensions.Add( new X509EnhancedKeyUsageExtension( oidCollection, false ) ); // Add CRL Distribution Point (CDP) req.CertificateExtensions.Add( new System.Security.Cryptography.X509Certificates.X509Extension( new Oid(X509Extensions.CrlDistributionPoints.Id), new CrlDistPoint( new[] { new DistributionPoint( new DistributionPointName( new GeneralNames( new GeneralName( GeneralName.UniformResourceIdentifier, CAConfig.CrlDistributionPoint ) ) ), null, null ) } ).GetDerEncoded(), false ) ); X509Certificate2 coreCaPublicCert = new X509Certificate2(coreCACert.Export(X509ContentType.Cert)); if (coreCaPublicCert.HasPrivateKey) { _logger.LogError("Core CA public certificate exported with private key!"); throw new CryptographicUnexpectedOperationException(); } // Use transaction to prevent race conditions on the serial number X509Certificate2 userCert; using ( IDbContextTransaction scope = _caDBModifier.GetScope() ) { SerialNumber serialNr = _caDBModifier.GetMaxSerialNr(); // It is necessary to use this constructor to be able to sign keys // that use different algorithms than the one for the core CA's key userCert = req.Create( coreCACert.SubjectName, X509SignatureGenerator.CreateForRSA( (RSA)coreCACert.PrivateKey, RSASignaturePadding.Pss ), DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(CAConfig.UserCertValidityPeriod), serialNr.SerialNrBytes ); _caDBModifier.RevokeAllCertificatesOfUser(user); // Add certificate to DB _caDBModifier.AddCertificate( new PublicCertificate { SerialNr = serialNr.SerialNr, Uid = user.Id, Certificate = Convert.ToBase64String( userCert.Export(X509ContentType.Cert) ), IsRevoked = false } ); scope.Commit(); } var collection = new X509Certificate2Collection(); X509Certificate2 userCertWithPrivKey; if (privKey is RSA rsa) { userCertWithPrivKey = userCert.CopyWithPrivateKey(rsa); } else if (privKey is ECDsa dsa) { userCertWithPrivKey = userCert.CopyWithPrivateKey(dsa); } else { throw new CryptographicUnexpectedOperationException(); } collection.Add(userCertWithPrivKey); collection.Add(coreCaPublicCert); BackupPrivateKey(privKeyExport, user.Id + '_' + userCert.Thumbprint + ".pem.enc"); byte[] certBytes = collection.Export(X509ContentType.Pkcs12, certRequest.CertPassphrase); string pkcs12ArchiveB64 = Convert.ToBase64String(certBytes); // Add encrypted private key to DB _caDBModifier.AddPrivateKey( new PrivateKey { Uid = user.Id, KeyPkcs12 = pkcs12ArchiveB64 } ); _logger.LogInformation("Successfully issued new certificate for user " + user.Id); return(Ok( new UserCertificate { Pkcs12Archive = pkcs12ArchiveB64 } )); } else { _logger.LogWarning( "Unauthorized attempt to issue certificate for user " + certRequest.Uid ); return(Unauthorized()); } }
internal static void RegisterSuite(CipherSuite suite, TlsCipherAlgorithm cipher, TlsHashAlgorithm digest, TlsSignatureAlgorithm signature, TlsKeyExchange exchange) { Suites.Add(suite); CipherMapping.Add(suite, cipher); DigestMapping.Add(suite, digest); SignatureMapping.Add(suite, signature); KeyExchangeMapping.Add(suite, exchange); }
public Cipher(CipherSuite suite, BulkEncryptionAlgorithm encrypalgo, MACAlgorithm macalgo, byte nBlockSize, byte nIVSize, int nKeyBits, byte nKeyMaterialSize) { CipherSuite = suite; BulkEncryptionAlgorithm = encrypalgo; MACAlgorithm = macalgo; BlockSizeBytes = nBlockSize; IVSize = nIVSize; KeySizeBits= nKeyBits; KeyMaterialLength = nKeyMaterialSize; KeyBlockSize = (this.KeyMaterialLength + this.HashSize + this.IVSize) << 1; }
public ServerHelloMessage(TlsVersion version, byte[] randomBytes, byte[] sessionId, HelloExtension[] extensions, CipherSuite cipherSuite, CompressionMethod compressionMethod) : base(HandshakeType.ServerHello, version, randomBytes, sessionId, extensions) { CipherSuite = cipherSuite; CompressionMethod = compressionMethod; }
internal static bool IsSupported(CipherSuite suite) { return _list.ContainsKey (suite); }
internal static CipherSuiteInfo GetSuiteInfo(CipherSuite suite) { return _list[suite]; }
private void ProcessServerHello(IByteBuffer body) { ProtocolVersion recordLayerVersion = recordLayer.GetReadVersion(); ReportServerVersion(recordLayerVersion); recordLayer.SetWriteVersion(recordLayerVersion); AsyncDtlsSecurityParameters securityParameters = (AsyncDtlsSecurityParameters)clientState.ClientContext.SecurityParameters; ProtocolVersion server_version = ProtocolVersion.Get(body.ReadByte() & 0xFF, body.ReadByte() & 0xFF); ReportServerVersion(server_version); byte[] serverRandom = new byte[32]; body.ReadBytes(serverRandom); securityParameters.SetServerRandom(serverRandom); byte[] selectedSessionID = new byte[body.ReadByte() & 0x0FF]; if (selectedSessionID.Length > 0) { body.ReadBytes(selectedSessionID); } clientState.SelectedSessionID = selectedSessionID; if (selectedSessionID.Length > 32) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } clientState.Client.NotifySessionID(selectedSessionID); clientState.ResumedSession = selectedSessionID.Length > 0 && clientState.TlsSession != null && ArrayUtils.Equals(clientState.SelectedSessionID, clientState.TlsSession.SessionID); int selectedCipherSuite = body.ReadUnsignedShort(); Boolean inOfferedCipherSuites = false; for (int i = 0; i < clientState.OfferedCipherSuites.Length; i++) { if (selectedCipherSuite == clientState.OfferedCipherSuites[i]) { inOfferedCipherSuites = true; break; } } if (!inOfferedCipherSuites || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL || CipherSuite.IsScsv(selectedCipherSuite) || !DtlsHelper.GetMinimumVersion(selectedCipherSuite).IsEqualOrEarlierVersionOf(clientState.ClientContext.ServerVersion.GetEquivalentTLSVersion())) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } switch (DtlsHelper.GetEncryptionAlgorithm(selectedCipherSuite)) { case EncryptionAlgorithm.RC4_40: case EncryptionAlgorithm.RC4_128: throw new TlsFatalAlert(AlertDescription.internal_error); } clientState.Client.NotifySelectedCipherSuite(selectedCipherSuite); byte selectedCompressionMethod = body.ReadByte(); Boolean inOfferedCompressionMethods = false; for (int i = 0; i < clientState.OfferedCompressionMethods.Length; i++) { if (selectedCompressionMethod == clientState.OfferedCompressionMethods[i]) { inOfferedCompressionMethods = true; break; } } if (!inOfferedCompressionMethods) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } clientState.Client.NotifySelectedCompressionMethod(selectedCompressionMethod); clientState.ServerExtensions = DtlsHelper.ReadSelectedExtensions(body); if (clientState.ServerExtensions != null) { foreach (Int32 extType in clientState.ServerExtensions.Keys) { if (extType.Equals(DtlsHelper.EXT_RenegotiationInfo)) { continue; } if (!clientState.ClientExtensions.Contains(extType)) { throw new TlsFatalAlert(AlertDescription.unsupported_extension); } } } byte[] renegExtData = null; if (clientState.ServerExtensions.Contains(DtlsHelper.EXT_RenegotiationInfo)) { renegExtData = (byte[])clientState.ServerExtensions[DtlsHelper.EXT_RenegotiationInfo]; } if (renegExtData != null) { clientState.SecureRenegotiation = true; if (!ArrayUtils.Equals(renegExtData, DtlsHelper.EMPTY_BYTES_WITH_LENGTH)) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } } if (clientState.SecureRenegotiation) { clientState.Client.NotifySecureRenegotiation(clientState.SecureRenegotiation); } IDictionary sessionClientExtensions = clientState.ClientExtensions; IDictionary sessionServerExtensions = clientState.ServerExtensions; if (clientState.ResumedSession) { if (selectedCipherSuite != clientState.SessionParameters.CipherSuite || selectedCompressionMethod != clientState.SessionParameters.CompressionAlgorithm) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } sessionClientExtensions = null; sessionServerExtensions = (Dictionary <Int32, byte[]>)clientState.SessionParameters.ReadServerExtensions(); } securityParameters.SetCipherSuite(selectedCipherSuite); securityParameters.SetCompressionAlgorithm(selectedCompressionMethod); if (sessionServerExtensions != null) { byte[] encryptThenMac = null; if (sessionServerExtensions.Contains(DtlsHelper.EXT_encrypt_then_mac)) { encryptThenMac = (byte[])sessionServerExtensions[DtlsHelper.EXT_encrypt_then_mac]; } if (encryptThenMac != null && encryptThenMac.Length > 0) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } Boolean serverSentEncryptThenMAC = encryptThenMac != null; if (serverSentEncryptThenMAC && DtlsHelper.GetCipherType(securityParameters.CipherSuite) != CipherType.block) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } securityParameters.SetEncryptThenMAC(serverSentEncryptThenMAC); byte[] extendedMacSecret = null; if (sessionServerExtensions.Contains(DtlsHelper.EXT_extended_master_secret)) { extendedMacSecret = (byte[])sessionServerExtensions[DtlsHelper.EXT_extended_master_secret]; } if (extendedMacSecret != null && extendedMacSecret.Length > 0) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } securityParameters.SetExtendedMasterSecret(extendedMacSecret != null); securityParameters.SetMaxFragmentLength(DtlsHelper.EvaluateMaxFragmentLengthExtension(clientState.ResumedSession, sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter)); byte[] truncatedHMAC = null; if (sessionServerExtensions.Contains(DtlsHelper.EXT_truncated_hmac)) { truncatedHMAC = (byte[])sessionServerExtensions[DtlsHelper.EXT_truncated_hmac]; } if (truncatedHMAC != null && truncatedHMAC.Length > 0) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } securityParameters.SetTruncatedHMac(truncatedHMAC != null); byte[] statusRequest = null; if (sessionServerExtensions.Contains(DtlsHelper.EXT_status_request)) { statusRequest = (byte[])sessionServerExtensions[DtlsHelper.EXT_status_request]; } if (statusRequest != null && statusRequest.Length > 0) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } clientState.AllowCertificateStatus = (!clientState.ResumedSession && statusRequest != null); byte[] sessionTicket = null; if (sessionServerExtensions.Contains(DtlsHelper.EXT_SessionTicket)) { sessionTicket = (byte[])sessionServerExtensions[DtlsHelper.EXT_SessionTicket]; } if (sessionTicket != null && sessionTicket.Length > 0) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } clientState.ExpectSessionTicket = (!clientState.ResumedSession && sessionTicket != null); } if (sessionClientExtensions != null) { clientState.Client.ProcessServerExtensions(sessionServerExtensions); } securityParameters.SetPrfAlgorithm(DtlsHelper.GetPRFAlgorithm(clientState.ClientContext.ServerVersion, securityParameters.CipherSuite)); securityParameters.SetVerifyDataLength(12); }
public void TLSv12Test() { byte[] finished2eb = new byte[] { 0x16, 0x03, 0x03, 0x00, 0x28, 0x77, 0xb7, 0x66, 0x18, 0x6f, 0x70, 0x52, 0x14, 0xc9, 0xa4, 0xbc, 0xbf, 0x26, 0x05, 0xf7, 0x99, 0x42, 0xb1, 0xc5, 0xc3, 0xcf, 0x3c, 0xb6, 0x48, 0x34, 0xfc, 0xd6, 0x35, 0x45, 0xf0, 0x12, 0xce, 0x1b, 0x0b, 0xff, 0x94, 0x15, 0x8f, 0x56, 0xda }; byte[] finished1db = new byte[] { 0x16, 0x03, 0x03, 0x00, 0x10, 0x14, 0x00, 0x00, 0x0C, 0x01, 0xE4, 0xC1, 0xFF, 0x6B, 0x7E, 0x2F, 0x6F, 0x6B, 0xC5, 0x16, 0xE6 }; byte[] finished2db = new byte[] { 0x16, 0x03, 0x03, 0x00, 0x10, 0x14, 0x00, 0x00, 0x0C, 0x83, 0x51, 0x75, 0x4D, 0x01, 0x37, 0x51, 0xEE, 0x72, 0x2F, 0xAE, 0x90 }; byte[] crandom = new byte[] { 0x4e, 0x61, 0xfd, 0x0b, 0x16, 0x0e, 0x3c, 0x92, 0xa0, 0x15, 0x90, 0x61, 0xfb, 0x2e, 0x51, 0xb4, 0x8f, 0xb0, 0xf5, 0xf2, 0x67, 0x4e, 0x20, 0x7f, 0xc3, 0x0d, 0x8e, 0x85, 0xdb, 0xfb, 0x58, 0xac }; byte[] srandom = new byte[] { 0x4e, 0x61, 0xfd, 0xe6, 0xf9, 0x06, 0x4d, 0x7c, 0x4c, 0x5b, 0x0b, 0x72, 0x6a, 0xba, 0x86, 0x76, 0xd9, 0x7d, 0xce, 0xcc, 0xd5, 0x24, 0x60, 0x6e, 0xaf, 0x16, 0x0f, 0x85, 0x52, 0x8d, 0xba, 0x86 }; byte[] master = new byte[] { 0xCA, 0xCB, 0xE5, 0x65, 0x39, 0x78, 0xFC, 0xCE, 0x18, 0xD8, 0x1C, 0xD8, 0xAD, 0x4E, 0x5E, 0x91, 0x18, 0x2B, 0x0E, 0xEF, 0x60, 0x13, 0xBB, 0xBF, 0xD8, 0x62, 0x77, 0x7F, 0xA3, 0xEF, 0x76, 0xAB, 0x7E, 0x3A, 0x26, 0xF2, 0xE1, 0xB8, 0x50, 0x46, 0x65, 0x85, 0x04, 0x23, 0xCC, 0x52, 0x2C, 0x87 }; Record finished1 = GetRecord(finished1db); Record finished2 = GetRecord(finished2eb); CipherSuitePluginManager pluginManager = GetPluginManager(); RecordHandler recordHandler = new RecordHandler(ProtocolVersion.SSL3_0, true); // Check that GCM suite is not available in TLS 1.1 CipherSuite nullSuite = pluginManager.GetCipherSuite(ProtocolVersion.TLS1_1, 0x00a2); Assert.IsNull(nullSuite); // Check that GCM suite is available in TLS 1.2 CipherSuite cipherSuite = pluginManager.GetCipherSuite(ProtocolVersion.TLS1_2, 0x00a2); Assert.IsNotNull(cipherSuite); // Set correct cipher suite ConnectionState connectionState = new ConnectionState(crandom, srandom, master); recordHandler.SetCipherSuite(cipherSuite, connectionState); // Test that initial state doesn't modify records recordHandler.ProcessOutputRecord(finished1); recordHandler.ProcessInputRecord(finished2); Assert.AreEqual(finished1db, finished1.GetBytes()); Assert.AreEqual(finished2eb, finished2.GetBytes()); recordHandler.ChangeLocalState(); recordHandler.ProcessOutputRecord(finished1); recordHandler.ChangeRemoteState(); recordHandler.ProcessInputRecord(finished2); Assert.AreEqual(finished2db, finished2.GetBytes()); }
public void SetCipherSuite(CipherSuite suite, AsymmetricAlgorithm signAlgo) { CipherSuiteInfo info = SupportedCipherSuites.GetSuiteInfo (suite); if (info == null) throw new NotSupportedException (); _bulk_cipher = info.BulkCipherAlgorithm; _cipherType = info.CipherType; _enc_key_length = info.EncKeyLength; _block_length = info.BlockLength; _fixed_iv_length = info.FixedIVLength; _record_iv_length = info.RecordIVLength; _mac = info.MACAlgorithm; _mac_length = info.MACLength; _mac_key_length = info.MACKeyLength; _keyExchange = info.KeyExchangeAlgorithm; // TODO: TLS1.2spec ? switch (_prfType) { case PRFAlgorithm.MD5_AND_SHA1: _prf = new MD5_AND_SHA1 (); break; case PRFAlgorithm.SSL3: _prf = new SSL3_PRF (this); break; default: throw new NotSupportedException (); } switch (_keyExchange) { case KeyExchangeAlgorithm.ECDHE_ECDSA: _keyExchanger = new ECDHE_ECDSA ((openCrypto.EllipticCurve.Signature.ECDSA)signAlgo); break; case KeyExchangeAlgorithm.DHE_DSS: _keyExchanger = new DHE_DSS ((DSACryptoServiceProvider)signAlgo); break; case KeyExchangeAlgorithm.RSA: _keyExchanger = new KeyExchange.RSA ((RSACryptoServiceProvider)signAlgo); break; default: throw new NotImplementedException (); } }
public static Cipher FindCipher(CipherSuite suite) { if (CommonCiphers.ContainsKey(suite) == true) return CommonCiphers[suite]; return null; }
private void ProcessHandshakeMessage(HandshakeType type, byte[] buf) { MemoryStream inStr = new MemoryStream(buf, false); /* * Check the type. */ switch (type) { case HandshakeType.certificate: { switch (connection_state) { case CS_SERVER_HELLO_RECEIVED: { // Parse the Certificate message and send to cipher suite Certificate serverCertificate = Certificate.Parse(inStr); AssertEmpty(inStr); this.keyExchange.ProcessServerCertificate(serverCertificate); this.authentication = tlsClient.GetAuthentication(); this.authentication.NotifyServerCertificate(serverCertificate); break; } default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } connection_state = CS_SERVER_CERTIFICATE_RECEIVED; break; } case HandshakeType.finished: switch (connection_state) { case CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED: /* * Read the checksum from the finished message, it has always 12 bytes. */ byte[] serverVerifyData = new byte[12]; TlsUtilities.ReadFully(serverVerifyData, inStr); AssertEmpty(inStr); /* * Calculate our own checksum. */ byte[] expectedServerVerifyData = TlsUtilities.PRF( securityParameters.masterSecret, "server finished", rs.GetCurrentHash(), 12); /* * Compare both checksums. */ if (!Arrays.ConstantTimeAreEqual(expectedServerVerifyData, serverVerifyData)) { /* * Wrong checksum in the finished message. */ this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); } connection_state = CS_DONE; /* * We are now ready to receive application data. */ this.appDataReady = true; break; default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } break; case HandshakeType.server_hello: switch (connection_state) { case CS_CLIENT_HELLO_SEND: /* * Read the server hello message */ TlsUtilities.CheckVersion(inStr, this); /* * Read the server random */ securityParameters.serverRandom = new byte[32]; TlsUtilities.ReadFully(securityParameters.serverRandom, inStr); byte[] sessionID = TlsUtilities.ReadOpaque8(inStr); if (sessionID.Length > 32) { this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); } this.tlsClient.NotifySessionID(sessionID); /* * Find out which CipherSuite the server has chosen and check that * it was one of the offered ones. */ CipherSuite selectedCipherSuite = (CipherSuite)TlsUtilities.ReadUint16(inStr); if (!ArrayContains(offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); } this.tlsClient.NotifySelectedCipherSuite(selectedCipherSuite); /* * Find out which CompressionMethod the server has chosen and check that * it was one of the offered ones. */ CompressionMethod selectedCompressionMethod = (CompressionMethod)TlsUtilities.ReadUint8(inStr); if (!ArrayContains(offeredCompressionMethods, selectedCompressionMethod)) { this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); } this.tlsClient.NotifySelectedCompressionMethod(selectedCompressionMethod); /* * RFC3546 2.2 The extended server hello message format MAY be * sent in place of the server hello message when the client has * requested extended functionality via the extended client hello * message specified in Section 2.1. * ... * Note that the extended server hello message is only sent in response * to an extended client hello message. This prevents the possibility * that the extended server hello message could "break" existing TLS 1.0 * clients. */ /* * TODO RFC 3546 2.3 * If [...] the older session is resumed, then the server MUST ignore * extensions appearing in the client hello, and send a server hello * containing no extensions. */ // ExtensionType -> byte[] IDictionary serverExtensions = Platform.CreateHashtable(); if (inStr.Position < inStr.Length) { // Process extensions from extended server hello byte[] extBytes = TlsUtilities.ReadOpaque16(inStr); MemoryStream ext = new MemoryStream(extBytes, false); while (ext.Position < ext.Length) { ExtensionType extType = (ExtensionType)TlsUtilities.ReadUint16(ext); byte[] extValue = TlsUtilities.ReadOpaque16(ext); // Note: RFC 5746 makes a special case for EXT_RenegotiationInfo if (extType != ExtensionType.renegotiation_info && !clientExtensions.Contains(extType)) { /* * RFC 3546 2.3 * Note that for all extension types (including those defined in * future), the extension type MUST NOT appear in the extended server * hello unless the same extension type appeared in the corresponding * client hello. Thus clients MUST abort the handshake if they receive * an extension type in the extended server hello that they did not * request in the associated (extended) client hello. */ this.FailWithError(AlertLevel.fatal, AlertDescription.unsupported_extension); } if (serverExtensions.Contains(extType)) { /* * RFC 3546 2.3 * Also note that when multiple extensions of different types are * present in the extended client hello or the extended server hello, * the extensions may appear in any order. There MUST NOT be more than * one extension of the same type. */ this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); } serverExtensions.Add(extType, extValue); } } AssertEmpty(inStr); /* * RFC 5746 3.4. When a ServerHello is received, the client MUST check if it * includes the "renegotiation_info" extension: */ { bool secure_negotiation = serverExtensions.Contains(ExtensionType.renegotiation_info); /* * If the extension is present, set the secure_renegotiation flag * to TRUE. The client MUST then verify that the length of the * "renegotiated_connection" field is zero, and if it is not, MUST * abort the handshake (by sending a fatal handshake_failure * alert). */ if (secure_negotiation) { byte[] renegExtValue = (byte[])serverExtensions[ExtensionType.renegotiation_info]; if (!Arrays.ConstantTimeAreEqual(renegExtValue, CreateRenegotiationInfo(emptybuf))) { this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); } } tlsClient.NotifySecureRenegotiation(secure_negotiation); } if (clientExtensions != null) { tlsClient.ProcessServerExtensions(serverExtensions); } this.keyExchange = tlsClient.GetKeyExchange(); connection_state = CS_SERVER_HELLO_RECEIVED; break; default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } break; case HandshakeType.server_hello_done: switch (connection_state) { case CS_SERVER_CERTIFICATE_RECEIVED: case CS_SERVER_KEY_EXCHANGE_RECEIVED: case CS_CERTIFICATE_REQUEST_RECEIVED: // NB: Original code used case label fall-through if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED) { // There was no server key exchange message; check it's OK this.keyExchange.SkipServerKeyExchange(); } AssertEmpty(inStr); connection_state = CS_SERVER_HELLO_DONE_RECEIVED; TlsCredentials clientCreds = null; if (certificateRequest == null) { this.keyExchange.SkipClientCredentials(); } else { clientCreds = this.authentication.GetClientCredentials(certificateRequest); Certificate clientCert; if (clientCreds == null) { this.keyExchange.SkipClientCredentials(); clientCert = Certificate.EmptyChain; } else { this.keyExchange.ProcessClientCredentials(clientCreds); clientCert = clientCreds.Certificate; } SendClientCertificate(clientCert); } /* * Send the client key exchange message, depending on the key * exchange we are using in our CipherSuite. */ SendClientKeyExchange(); connection_state = CS_CLIENT_KEY_EXCHANGE_SEND; if (clientCreds != null && clientCreds is TlsSignerCredentials) { TlsSignerCredentials signerCreds = (TlsSignerCredentials)clientCreds; byte[] md5andsha1 = rs.GetCurrentHash(); byte[] clientCertificateSignature = signerCreds.GenerateCertificateSignature( md5andsha1); SendCertificateVerify(clientCertificateSignature); connection_state = CS_CERTIFICATE_VERIFY_SEND; } /* * Now, we send change cipher state */ byte[] cmessage = new byte[1]; cmessage[0] = 1; rs.WriteMessage(ContentType.change_cipher_spec, cmessage, 0, cmessage.Length); connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND; /* * Calculate the master_secret */ byte[] pms = this.keyExchange.GeneratePremasterSecret(); securityParameters.masterSecret = TlsUtilities.PRF(pms, "master secret", TlsUtilities.Concat(securityParameters.clientRandom, securityParameters.serverRandom), 48); // TODO Is there a way to ensure the data is really overwritten? /* * RFC 2246 8.1. The pre_master_secret should be deleted from * memory once the master_secret has been computed. */ Array.Clear(pms, 0, pms.Length); /* * Initialize our cipher suite */ rs.ClientCipherSpecDecided(tlsClient.GetCompression(), tlsClient.GetCipher()); /* * Send our finished message. */ byte[] clientVerifyData = TlsUtilities.PRF(securityParameters.masterSecret, "client finished", rs.GetCurrentHash(), 12); MemoryStream bos = new MemoryStream(); TlsUtilities.WriteUint8((byte)HandshakeType.finished, bos); TlsUtilities.WriteOpaque24(clientVerifyData, bos); byte[] message = bos.ToArray(); rs.WriteMessage(ContentType.handshake, message, 0, message.Length); this.connection_state = CS_CLIENT_FINISHED_SEND; break; default: this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); break; } break; case HandshakeType.server_key_exchange: { switch (connection_state) { case CS_SERVER_HELLO_RECEIVED: case CS_SERVER_CERTIFICATE_RECEIVED: { // NB: Original code used case label fall-through if (connection_state == CS_SERVER_HELLO_RECEIVED) { // There was no server certificate message; check it's OK this.keyExchange.SkipServerCertificate(); this.authentication = null; } this.keyExchange.ProcessServerKeyExchange(inStr); AssertEmpty(inStr); break; } default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED; break; } case HandshakeType.certificate_request: switch (connection_state) { case CS_SERVER_CERTIFICATE_RECEIVED: case CS_SERVER_KEY_EXCHANGE_RECEIVED: { // NB: Original code used case label fall-through if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED) { // There was no server key exchange message; check it's OK this.keyExchange.SkipServerKeyExchange(); } if (this.authentication == null) { /* * RFC 2246 7.4.4. It is a fatal handshake_failure alert * for an anonymous server to request client identification. */ 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); 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; } default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } this.connection_state = CS_CERTIFICATE_REQUEST_RECEIVED; break; case HandshakeType.hello_request: /* * RFC 2246 7.4.1.1 Hello request * This message will be ignored by the client if the client is currently * negotiating a session. This message may be ignored by the client if it * does not wish to renegotiate a session, or the client may, if it wishes, * respond with a no_renegotiation alert. */ if (connection_state == CS_DONE) { // Renegotiation not supported yet SendAlert(AlertLevel.warning, AlertDescription.no_renegotiation); } break; case HandshakeType.client_key_exchange: case HandshakeType.certificate_verify: case HandshakeType.client_hello: default: // We do not support this! this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } }
public static void Write(this EndianBinaryWriter writer, CipherSuite value) { writer.Write((ushort)value); }
public ClientHello(byte[] clientHelloBytes) : base(clientHelloBytes) { var index = 0; var _protocolVersion = Utils.ToUInt16(clientHelloBytes, index); index += 2; var bytes_random = new byte[32]; Buffer.BlockCopy(clientHelloBytes, index, bytes_random, 0, bytes_random.Length); index += 32; var _sessionIDLength = clientHelloBytes[index]; byte[] _sessionID = null; index++; // if sessionID exists if (_sessionIDLength > 0) { _sessionID = new byte[_sessionIDLength]; Buffer.BlockCopy(clientHelloBytes, index, _sessionID, 0, _sessionIDLength); index += _sessionIDLength; } var _cipherSuiteLen = Utils.ToUInt16(clientHelloBytes, index); _cipherSuiteLen = (ushort)(_cipherSuiteLen / 2); index += 2; CipherSuite[] _cipherSuites = new CipherSuite[_cipherSuiteLen]; for (int csi = 0; csi < _cipherSuiteLen; csi++) { _cipherSuites[csi] = (CipherSuite)Utils.ToUInt16(clientHelloBytes, index); index += 2; } var _compressionMethodLen = clientHelloBytes[index]; index++; CompressionMethod[] _compressionMethods = new CompressionMethod[_compressionMethodLen]; for (int cmi = 0; cmi < _compressionMethodLen; cmi++) { _compressionMethods[cmi] = (CompressionMethod)clientHelloBytes[index]; index++; } var _extensionsLength = Utils.ToUInt16(clientHelloBytes, index); index += 2; var bytes_extensions = new byte[_extensionsLength]; Buffer.BlockCopy(clientHelloBytes, index, bytes_extensions, 0, _extensionsLength); var _extensions = TLS.Extensions.Extension.Extract(bytes_extensions); this.ProtocolVersion = (ProtocolVersion)_protocolVersion; this.Random = new ValueTypes.Random(bytes_random); this.Session = new ValueTypes.Session(_sessionID); this.CipherSuites = new ValueTypes.CipherSuites(_cipherSuites); this.CompressionMethods = new ValueTypes.CompressionMethods(_compressionMethods); this.Extensions = _extensions; this.ExtensionsLength = TLS.Extensions.Extension.GetLength(_extensions); }
private static bool IsSupported(CipherSuite suite) { // suite if (!Suites.Contains(suite)) { return false; } // cipher if (!CipherMapping.ContainsKey(suite)) { return false; } if (!IsSupported(CipherMapping[suite])) { return false; } // digest if (!DigestMapping.ContainsKey(suite)) { return false; } if (!IsSupported(DigestMapping[suite])) { return false; } // signature if (!SignatureMapping.ContainsKey(suite)) { return false; } if (!IsSupported(SignatureMapping[suite])) { return false; } // keyexchange if (!KeyExchangeMapping.ContainsKey(suite)) { return false; } if (!IsSupported(KeyExchangeMapping[suite])) { return false; } return true; }
/// <summary> /// Reads this object in from an array, returning how many bytes were read, or 0 if there is an error or not enough data /// </summary> /// <param name="bData"></param> /// <param name="nStartAt"></param> /// <returns></returns> public uint ReadFromArray(byte[] bData, int nStartAt) { CipherSuites.Clear(); CompressionMethods.Clear(); uint nReadSoFar = 0; if (bData.Length < (nStartAt + 35)) { return(0); } Version = ByteHelper.ReadUshortBigEndian(bData, (int)(nStartAt + nReadSoFar)); nReadSoFar += 2; nReadSoFar += RandomStruct.ReadFromArray(bData, (int)(nStartAt + nReadSoFar)); SessionIDLength = bData[nStartAt + nReadSoFar]; nReadSoFar += 1; if (SessionIDLength > 0) { if (bData.Length < (nStartAt + nReadSoFar + SessionIDLength)) { return(0); } this.SessionID = ByteHelper.ReadByteArray(bData, (int)(nStartAt + nReadSoFar), (int)SessionIDLength); nReadSoFar += SessionIDLength; } if (bData.Length < (nStartAt + nReadSoFar + 2)) { return(0); } CipherSuitesLength = ByteHelper.ReadUshortBigEndian(bData, (int)(nStartAt + nReadSoFar)); nReadSoFar += 2; if (CipherSuitesLength > 0) { if (bData.Length < (nStartAt + nReadSoFar + CipherSuitesLength)) { return(0); } for (int i = 0; i < CipherSuitesLength / 2; i++) { CipherSuite nNextCipherSuite = (CipherSuite)ByteHelper.ReadUshortBigEndian(bData, (int)(nStartAt + nReadSoFar)); nReadSoFar += 2; CipherSuites.Add(nNextCipherSuite); } } if (bData.Length < (nStartAt + nReadSoFar + 2)) { return(0); } CompressionMethodsLength = ByteHelper.ReadByte(bData, (int)(nStartAt + nReadSoFar)); nReadSoFar += 1; if (CompressionMethodsLength > 0) { if (bData.Length < (nStartAt + nReadSoFar + CompressionMethodsLength)) { return(0); } for (int i = 0; i < CipherSuitesLength / 2; i++) { CompressionMethod bNextCompressionMethod = (CompressionMethod)ByteHelper.ReadByte(bData, (int)(nStartAt + nReadSoFar)); nReadSoFar += 1; CompressionMethods.Add(bNextCompressionMethod); } } return(nReadSoFar); }
/// <summary>Add a new encryption zone.</summary> /// <remarks> /// Add a new encryption zone. /// <p/> /// Called while holding the FSDirectory lock. /// </remarks> /// <param name="inodeId">of the encryption zone</param> /// <param name="keyName">encryption zone key name</param> internal virtual void AddEncryptionZone(long inodeId, CipherSuite suite, CryptoProtocolVersion version, string keyName) { System.Diagnostics.Debug.Assert(dir.HasWriteLock()); UnprotectedAddEncryptionZone(inodeId, suite, version, keyName); }
public static CipherSuite InitializeCipherSuite(byte[] master, byte[] clientrnd, byte[] serverrnd, CipherDefinition definition, ConnectionEnd entity) { CipherSuite ret = new CipherSuite(); SymmetricAlgorithm bulk = (SymmetricAlgorithm)Activator.CreateInstance(definition.BulkCipherAlgorithm); if (definition.BulkIVSize > 0) { bulk.Mode = CipherMode.CBC; } bulk.Padding = PaddingMode.None; bulk.BlockSize = definition.BulkIVSize * 8; // get the keys and IVs byte[] client_mac, server_mac, client_key, server_key, client_iv, server_iv; byte[] random = new byte[64]; Array.Copy(serverrnd, 0, random, 0, 32); Array.Copy(clientrnd, 0, random, 32, 32); PseudoRandomDeriveBytes prf = new PseudoRandomDeriveBytes(master, "key expansion", random); client_mac = prf.GetBytes(definition.HashSize); server_mac = prf.GetBytes(definition.HashSize); client_key = prf.GetBytes(definition.BulkKeySize); server_key = prf.GetBytes(definition.BulkKeySize); client_iv = prf.GetBytes(definition.BulkIVSize); server_iv = prf.GetBytes(definition.BulkIVSize); prf.Dispose(); if (definition.Exportable) // make some extra modifications if the keys are exportable { Array.Copy(clientrnd, 0, random, 0, 32); Array.Copy(serverrnd, 0, random, 32, 32); prf = new PseudoRandomDeriveBytes(client_key, "client write key", random); client_key = prf.GetBytes(definition.BulkExpandedSize); prf.Dispose(); prf = new PseudoRandomDeriveBytes(server_key, "server write key", random); server_key = prf.GetBytes(definition.BulkExpandedSize); prf.Dispose(); prf = new PseudoRandomDeriveBytes(new byte[0], "IV block", random); client_iv = prf.GetBytes(definition.BulkIVSize); server_iv = prf.GetBytes(definition.BulkIVSize); prf.Dispose(); } // generate the cipher objects if (entity == ConnectionEnd.Client) { ret.Encryptor = bulk.CreateEncryptor(client_key, client_iv); ret.Decryptor = bulk.CreateDecryptor(server_key, server_iv); ret.LocalHasher = new HMAC((HashAlgorithm)Activator.CreateInstance(definition.HashAlgorithm), client_mac); ret.RemoteHasher = new HMAC((HashAlgorithm)Activator.CreateInstance(definition.HashAlgorithm), server_mac); } else { ret.Encryptor = bulk.CreateEncryptor(server_key, server_iv); ret.Decryptor = bulk.CreateDecryptor(client_key, client_iv); ret.LocalHasher = new HMAC((HashAlgorithm)Activator.CreateInstance(definition.HashAlgorithm), server_mac); ret.RemoteHasher = new HMAC((HashAlgorithm)Activator.CreateInstance(definition.HashAlgorithm), client_mac); } // clear sensitive data Array.Clear(client_mac, 0, client_mac.Length); Array.Clear(server_mac, 0, server_mac.Length); Array.Clear(client_key, 0, client_key.Length); Array.Clear(server_key, 0, server_key.Length); Array.Clear(client_iv, 0, client_iv.Length); Array.Clear(server_iv, 0, server_iv.Length); Array.Clear(random, 0, random.Length); return(ret); }
void ProcessHandshake() { ClientHello clientHello = _recordLayer.Read() as ClientHello; if (clientHello == null) { throw new Exception(); } Console.WriteLine("[TLSServer] Receive ClientHello Version: {0}", clientHello.Version); Console.WriteLine("[TLSServer] CipherSuites"); for (int i = 0; i < clientHello.CipherSuites.Length; i++) { Console.WriteLine(" {0}", clientHello.CipherSuites[i]); } CipherSuite selected = _selector.Select(clientHello.CipherSuites); Console.WriteLine("[TLSServer] CipherSuite Selected. {0}", selected); if (selected == CipherSuite.NONE) { // Alertを送るべき? throw new Exception(); } CipherSuiteInfo selectedInfo = SupportedCipherSuites.GetSuiteInfo(selected); _sparams.SetVersion(clientHello.Version); _sparams.SetCipherSuite(selected, _signAlgo); _sparams.ClientRandom = clientHello.Random; _recordLayer.ProtocolVersion = clientHello.Version; byte[] serverRandom = new byte[RandomData.Size]; Extension[] serverExtensions = null; if (selectedInfo.IsECC) { serverExtensions = new Extension[] { new Extension(ExtensionType.EcPointFormats, new byte[] { 1, 0 }) } } ; RandomData.CreateRandomData(serverRandom, 0); _sparams.ServerRandom = serverRandom; ServerHello serverHello = new ServerHello(clientHello.Version, serverRandom, Utility.EmptyByteArray, selected, CompressionMethod.Null, serverExtensions); _recordLayer.Write(serverHello); Certificate serverCert = new Certificate(_certs); _recordLayer.Write(serverCert); if (Utility.IsNeedServerKeyExchangeMessage(_states.SecurityParameters.KeyExchangeAlgorithm)) { ServerKeyExchange serverExchange = new ServerKeyExchange(_sparams); _recordLayer.Write(serverExchange); } _recordLayer.Write(new ServerHelloDone()); TLSMessage msg = _recordLayer.Read(); ClientKeyExchange clientExchange = (ClientKeyExchange)msg; clientExchange.ComputeServerMasterSecret(_sparams); Console.WriteLine("MasterSecret"); Utility.Dump(_sparams.MasterSecret); _sparams.ComputeKeyBlock(); ChangeCipherSpec changeCipherSpec = (ChangeCipherSpec)_recordLayer.Read(); _recordLayer.EnableReceiveCipher(_sparams.CreateServerDecryptor(), _sparams.CreateClientWriteHMAC()); Finished finished = (Finished)_recordLayer.Read(); Console.WriteLine("VerifyData"); Utility.Dump(finished.VerifyData); Console.WriteLine("Computed VerifyData"); byte[] verifyData = _sparams.ComputeFinishedVerifyData(false); Utility.Dump(verifyData); if (!Utility.Equals(finished.VerifyData, 0, verifyData, 0, verifyData.Length)) { throw new Exception(); } _recordLayer.Write(ChangeCipherSpec.Instance); _recordLayer.EnableSendCipher(_sparams.CreateServerEncryptor(), _sparams.CreateServerWriteHMAC()); _recordLayer.ComputeHandshakeHash(true); verifyData = _sparams.ComputeFinishedVerifyData(true); Console.WriteLine("Finished VerifyData"); Utility.Dump(verifyData); finished = new Finished(_recordLayer.ProtocolVersion, verifyData); _recordLayer.Write(finished); }
private static CipherSuite SelectCipherSuite(CipherSuitePluginManager pluginManager, ProtocolVersion clientVersion, ProtocolVersion minVersion, ProtocolVersion maxVersion, List <CipherSuiteId> clientSuites, List <CipherSuiteId> serverSuites, ServerCertificateSelectionCallback certificateSelectionCallback, List <X509CertificateCollection> availableCertificates) { if (clientVersion < minVersion) { throw new AlertException(AlertDescription.ProtocolVersion, "Offered client version " + clientVersion + " lower than minimum supported version " + minVersion); } // Initialize our return value as null CipherSuite selectedCipherSuite = null; // Run as long as we either select a cipher suite or run out of versions ProtocolVersion selectedVersion = clientVersion < maxVersion ? clientVersion : maxVersion; while (selectedCipherSuite == null) { foreach (CipherSuiteId id in clientSuites) { if (!serverSuites.Contains(id)) { continue; } // Try initializing the cipher suite based on ID selectedCipherSuite = pluginManager.GetCipherSuite(selectedVersion, (ushort)id); if (selectedCipherSuite == null) { continue; } // Try selecting a suitable certificate for this cipher suite int certificateIndex = certificateSelectionCallback(selectedCipherSuite, availableCertificates.ToArray()); if (certificateIndex >= 0 && certificateIndex < availableCertificates.Count) { // We finally found the valid suite, break out from the loop break; } // No certificate was found for the suite, ignore selectedCipherSuite = null; } if (selectedCipherSuite != null) { break; } if (selectedVersion == minVersion) { break; } selectedVersion = selectedVersion.PreviousProtocolVersion; } if (selectedCipherSuite == null) { throw new AlertException(AlertDescription.HandshakeFailure, "None of the cipher suites offered by client is accepted"); } return(selectedCipherSuite); }
public ServerHello(ProtocolVersion protocolVersion, ValueTypes.Random random, ValueTypes.Session session, CipherSuite cipher, Extensions.Extension[] extensions = null) : base(null) { this.ProtocolVersion = protocolVersion; this.Random = random; this.Session = session; this.CipherSuite = cipher; this.CompressionMethod = CompressionMethod.NO_COMPRESSION; this.Extensions = extensions; this.ExtensionsLength = TLS.Extensions.Extension.GetLength(extensions); byte[] bytes_random = this.Random.Data; byte[] bytes_session = this.Session.Data; // length of the Handshake Header payload (aka the ServerHello message) int length = 2; // 2 bytes ProtocolVersion length += bytes_random.Length; // bytes ServerRandom length += bytes_session.Length; // 1 byte SessionIDLength + bytes SessionID length += 2; // 2 bytes CipherSuite length += 1; // 1 byte CompressionMethod length += 2; // 2 bytes ExtensionsLength length += this.ExtensionsLength; // total bytes of extensions Data = new byte[length]; int index = 0; // ProtocolVersion Data[index] = (byte)(((ushort)ProtocolVersion & 0xff00) >> 8); Data[index + 1] = (byte)((ushort)ProtocolVersion & 0x00ff); index += 2; // ServerRandom Buffer.BlockCopy(bytes_random, 0, Data, index, bytes_random.Length); index += bytes_random.Length; // SessionIDLength + SessionID Buffer.BlockCopy(bytes_session, 0, Data, index, bytes_session.Length); index += bytes_session.Length; // CipherSuite Data[index] = (byte)(((ushort)this.CipherSuite & 0xff00) >> 8); Data[index + 1] = (byte)((ushort)this.CipherSuite & 0x00ff); index += 2; // CompressionMethod Data[index] = (byte)this.CompressionMethod; index += 1; // ExtensionsLength Data[index] = (byte)((this.ExtensionsLength & 0xff00) >> 8); Data[index + 1] = (byte)(this.ExtensionsLength & 0x00ff); index += 2; // Extensions if (this.Extensions != null) { foreach (var e in this.Extensions) { var extBytes = e.Data; Buffer.BlockCopy(extBytes, 0, Data, index, extBytes.Length); index += extBytes.Length; } } }
protected override void ProcessAsTls1() { // Read protocol version this.processProtocol(this.ReadInt16()); // Read random - Unix time + Random bytes this.random = this.ReadBytes(32); // Read Session id int length = (int)ReadByte(); if (length > 0) { this.sessionId = this.ReadBytes(length); } // Read cipher suite short cipherCode = this.ReadInt16(); if (this.Context.SupportedCiphers.IndexOf(cipherCode) == -1) { // The server has sent an invalid ciphersuite throw new TlsException(AlertDescription.InsuficientSecurity, "Invalid cipher suite received from server"); } this.cipherSuite = this.Context.SupportedCiphers[cipherCode]; // Read compression methods ( always 0 ) this.compressionMethod = (SecurityCompressionType)this.ReadByte(); }
protected virtual void SelectCipher(TlsClientHello message) { var certificate = Config.Certificate; if (certificate == null) { throw new TlsException(AlertDescription.HandshakeFailure, "Missing server certificate"); } CipherSuiteCollection requestedCiphers; if (Settings.RequestedCiphers != null) { requestedCiphers = new CipherSuiteCollection(Context.NegotiatedProtocol, Settings.RequestedCiphers); } else { requestedCiphers = CipherSuiteFactory.GetDefaultCiphers(Context.NegotiatedProtocol); } HandshakeParameters.SupportedCiphers = requestedCiphers.Filter(cipher => { #if INSTRUMENTATION if (Context.HasInstrument(HandshakeInstrumentType.OverrideServerCertificateSelection)) { return(true); } #endif var exchangeAlgorithm = CipherSuiteFactory.GetExchangeAlgorithmType(Context.NegotiatedProtocol, cipher); return(CertificateManager.VerifyServerCertificate(Context, certificate, exchangeAlgorithm)); }); CipherSuite selectedCipher = null; foreach (var code in message.ClientCiphers) { var idx = HandshakeParameters.SupportedCiphers.IndexOf(code); if (idx < 0) { continue; } var cipher = HandshakeParameters.SupportedCiphers [idx]; selectedCipher = CipherSuiteFactory.CreateCipherSuite(Context.NegotiatedProtocol, cipher); break; } if (selectedCipher == null) { throw new TlsException(AlertDescription.HandshakeFailure, "Invalid cipher suite received from client"); } #if DEBUG_FULL if (Context.EnableDebugging) { selectedCipher.EnableDebugging = true; } #endif #if DEBUG_FULL if (Context.EnableDebugging) { DebugHelper.WriteLine("Selected Cipher: {0}", selectedCipher); } #endif // FIXME: Select best one. Session.PendingCrypto = selectedCipher.Initialize(true, Context.NegotiatedProtocol); Session.PendingCrypto.ServerCertificates = new X509CertificateCollection(); Session.PendingCrypto.ServerCertificates.Add(certificate); }
public void TLSv10Test() { byte[] finished1eb1 = new byte[] { 0x16, 0x03, 0x01, 0x00, 0x30, 0x78, 0x02, 0x93, 0x89, 0x26, 0x70, 0xDD, 0x57, 0x12, 0xD5, 0x47, 0xC5, 0xE3, 0x9E, 0xE7, 0x03, 0x2A, 0x41, 0x35, 0x46, 0xE3, 0x13, 0x06, 0xBB, 0x4F, 0x21, 0xEB, 0x3D, 0x5F, 0x42, 0xF6, 0xBF, 0x89, 0x4B, 0x43, 0x8C, 0x77, 0x29, 0xF9, 0x54, 0xDC, 0xCB, 0x0E, 0xE6, 0xA4, 0xA0, 0x13, 0xF8 }; byte[] finished1eb2 = new byte[] { 0x16, 0x03, 0x01, 0x00, 0x40, 0x78, 0x02, 0x93, 0x89, 0x26, 0x70, 0xdd, 0x57, 0x12, 0xd5, 0x47, 0xc5, 0xe3, 0x9e, 0xe7, 0x03, 0x2a, 0x41, 0x35, 0x46, 0xe3, 0x13, 0x06, 0xbb, 0x4f, 0x21, 0xeb, 0x3d, 0x5f, 0x42, 0xf6, 0xbf, 0x1f, 0x91, 0x7c, 0xf3, 0xf5, 0x07, 0x84, 0xc4, 0x51, 0x89, 0x73, 0xbb, 0xb1, 0x88, 0x35, 0xcd, 0x21, 0xa9, 0x2a, 0x1a, 0x08, 0xfc, 0x23, 0x4b, 0x9f, 0x9b, 0x0a, 0x83, 0x47, 0x2c, 0x2e, 0x81 }; byte[] finished2eb = new byte[] { 0x16, 0x03, 0x01, 0x00, 0x30, 0xde, 0x54, 0x89, 0x2f, 0x60, 0x2f, 0x3e, 0x88, 0x6f, 0x78, 0xac, 0xed, 0xf9, 0xf8, 0x56, 0x31, 0xbd, 0x55, 0x3f, 0x7f, 0x82, 0x41, 0xfa, 0x49, 0x4c, 0x16, 0x01, 0x13, 0x91, 0xcb, 0xcc, 0x78, 0x3f, 0x89, 0x86, 0xaa, 0x58, 0xd1, 0x73, 0x76, 0xb3, 0xa2, 0x82, 0x99, 0x02, 0x07, 0x95, 0x56 }; byte[] finished1db = new byte[] { 0x16, 0x03, 0x01, 0x00, 0x10, 0x14, 0x00, 0x00, 0x0C, 0x21, 0x39, 0xB0, 0xD0, 0x3F, 0x12, 0x1F, 0x3B, 0x76, 0x1A, 0xE7, 0x71 }; byte[] finished2db = new byte[] { 0x16, 0x03, 0x01, 0x00, 0x10, 0x14, 0x00, 0x00, 0x0C, 0xDE, 0x0C, 0x18, 0x26, 0x54, 0x99, 0x6F, 0x29, 0xA2, 0x72, 0x91, 0xC4 }; byte[] crandom = new byte[] { 0x4e, 0x60, 0xe1, 0xed, 0x13, 0x2c, 0x19, 0xe5, 0x44, 0xaf, 0xb2, 0xe1, 0x1d, 0x97, 0x67, 0x47, 0xaf, 0x5a, 0xb8, 0xf4, 0x7e, 0xcb, 0xbe, 0x42, 0x4f, 0x3b, 0x24, 0x9e, 0xff, 0x0f, 0x5d, 0x87 }; byte[] srandom = new byte[] { 0x4e, 0x60, 0xe2, 0xa4, 0x9e, 0x37, 0xea, 0x2a, 0xc1, 0xbe, 0xe9, 0x3d, 0x05, 0x04, 0xb9, 0x83, 0x57, 0x2a, 0x03, 0xf0, 0x1a, 0x6a, 0xe5, 0x53, 0x08, 0xa9, 0x01, 0xb0, 0x06, 0x2a, 0x9a, 0x79 }; byte[] master = new byte[] { 0xB2, 0xEC, 0xD1, 0x59, 0x9C, 0x97, 0x49, 0x58, 0xFB, 0x86, 0x9A, 0x65, 0xEB, 0x8F, 0x91, 0x31, 0x54, 0xAC, 0x41, 0xCD, 0xF8, 0x12, 0x8F, 0xCA, 0x25, 0xF0, 0x06, 0x91, 0xFE, 0xF3, 0x09, 0x7F, 0x04, 0x6F, 0x9D, 0x75, 0x24, 0x52, 0xCD, 0xC5, 0x69, 0xE2, 0x0C, 0xB2, 0xB3, 0xCD, 0xA0, 0x02 }; Record finished1 = GetRecord(finished1db); Record finished2 = GetRecord(finished2eb); CipherSuitePluginManager pluginManager = GetPluginManager(); RecordHandler recordHandler = new RecordHandler(ProtocolVersion.SSL3_0, true); CipherSuite cipherSuite = pluginManager.GetCipherSuite(ProtocolVersion.TLS1_0, 0x002f); Assert.IsNotNull(cipherSuite); // Set correct cipher suite ConnectionState connectionState = new ConnectionState(crandom, srandom, master); recordHandler.SetCipherSuite(cipherSuite, connectionState); // Test that initial state doesn't modify records recordHandler.ProcessOutputRecord(finished1); recordHandler.ProcessInputRecord(finished2); Assert.AreEqual(finished1db, finished1.GetBytes()); Assert.AreEqual(finished2eb, finished2.GetBytes()); recordHandler.ChangeLocalState(); recordHandler.ProcessOutputRecord(finished1); recordHandler.ChangeRemoteState(); recordHandler.ProcessInputRecord(finished2); if (finished1.GetBytes().Length == finished1eb1.Length) { Assert.AreEqual(finished1eb1, finished1.GetBytes()); } else { Assert.AreEqual(finished1eb2, finished1.GetBytes()); } Assert.AreEqual(finished2db, finished2.GetBytes()); }
public virtual void NotifySelectedCipherSuite(CipherSuite selectedCipherSuite) { this.selectedCipherSuite = selectedCipherSuite; }
/// <summary> /// Reads this object in from an array, returning how many bytes were read, or 0 if there is an error or not enough data /// </summary> /// <param name="bData"></param> /// <param name="nStartAt"></param> /// <returns></returns> public uint ReadFromArray(byte[] bData, int nStartAt) { uint nReadSoFar = 0; if (bData.Length < (nStartAt + 35)) return 0; Version = ByteHelper.ReadUshortBigEndian(bData, (int)(nStartAt + nReadSoFar)); nReadSoFar += 2; nReadSoFar += RandomStruct.ReadFromArray(bData, (int) (nStartAt+nReadSoFar)); SessionIDLength = bData[nStartAt + nReadSoFar]; nReadSoFar += 1; if (SessionIDLength > 0) { if (bData.Length < (nStartAt + nReadSoFar + SessionIDLength)) return 0; this.SessionID = ByteHelper.ReadByteArray(bData, (int)(nStartAt + nReadSoFar), (int)SessionIDLength); nReadSoFar += SessionIDLength; } CipherSuite = (CipherSuite) ByteHelper.ReadUshortBigEndian(bData, (int)(nStartAt + nReadSoFar)); nReadSoFar += 2; CompressionMethod = (CompressionMethod) ByteHelper.ReadByte(bData, (int)(nStartAt + nReadSoFar)); nReadSoFar += 1; return nReadSoFar; }
/* * Print the report on the provided writer (text version for * humans). */ internal void Print(TextWriter w) { w.WriteLine("Connection: {0}:{1}", connName, connPort); if (sni == null) { w.WriteLine("No SNI sent"); } else { w.WriteLine("SNI: {0}", sni); } if (ssl2Suites != null && ssl2Suites.Length > 0) { w.WriteLine(" {0}", M.VersionString(M.SSLv20)); foreach (int s in ssl2Suites) { w.WriteLine(" {0}", CipherSuite.ToNameV2(s)); } } SupportedCipherSuites last = null; foreach (int v in suites.Keys) { w.Write(" {0}:", M.VersionString(v)); SupportedCipherSuites scs = suites[v]; if (scs.Equals(last)) { w.WriteLine(" idem"); continue; } last = scs; w.WriteLine(); w.Write(" server selection: "); if (scs.PrefClient) { w.WriteLine("uses client preferences"); } else if (scs.PrefServer) { w.WriteLine("enforce server preferences"); } else { w.WriteLine("complex"); } foreach (int s in scs.Suites) { CipherSuite cs; string strength; string fsf; string anon; string kt; if (CipherSuite.ALL.TryGetValue(s, out cs)) { strength = cs.Strength.ToString(); fsf = cs.HasForwardSecrecy ? "f" : "-"; anon = cs.IsAnonymous ? "A" : "-"; kt = cs.ServerKeyType; } else { strength = "?"; fsf = "?"; anon = "?"; kt = "?"; } w.WriteLine(" {0}{1}{2} (key: {3,4}) {4}", strength, fsf, anon, kt, CipherSuite.ToName(s)); } } w.WriteLine("========================================="); if (ssl2Chain != null) { w.WriteLine("+++++ SSLv2 certificate"); PrintCert(w, ssl2Chain, 0); } w.WriteLine("+++++ SSLv3/TLS: {0} certificate chain(s)", chains.Count); foreach (X509Chain xchain in chains.Values) { int n = xchain.Elements.Length; w.WriteLine("+++ chain: length={0}", n); if (xchain.Decodable) { w.WriteLine("names match: {0}", xchain.NamesMatch ? "yes" : "no"); w.WriteLine("includes root: {0}", xchain.IncludesRoot ? "yes" : "no"); w.Write("signature hash(es):"); foreach (string name in xchain.SignHashes) { w.Write(" {0}", name); } w.WriteLine(); } else if (n == 0) { w.WriteLine("CHAIN IS EMPTY"); } else { w.WriteLine("CHAIN PROCESSING ERROR"); } for (int i = 0; i < n; i++) { w.WriteLine("+ certificate order: {0}", i); PrintCert(w, xchain, i); } } w.WriteLine("========================================="); w.WriteLine("Server compression support: {0}", DeflateCompress ? "yes" : "no"); if (serverTimeOffset == Int64.MinValue) { w.WriteLine("Server does not send its system time."); } else if (serverTimeOffset == Int64.MaxValue) { w.WriteLine("Server sends a random system time."); } else { DateTime dt = DateTime.UtcNow; dt = dt.AddMilliseconds((double)serverTimeOffset); w.WriteLine("Server time: {0:yyyy-MM-dd HH:mm:ss} UTC" + " (offset: {1} ms)", dt, serverTimeOffset); } w.WriteLine("Secure renegotiation support: {0}", doesRenego ? "yes" : "no"); w.WriteLine("SSLv2 ClientHello format (for SSLv3+): {0}", helloV2 ? "yes" : "no"); if (minDHSize > 0) { w.WriteLine("Minimum DH size: {0}", minDHSize); w.WriteLine("DH parameter reuse: {0}", kxReuseDH ? "yes" : " no"); } if (minECSize > 0) { w.WriteLine("Minimum EC size (no extension): {0}", minECSize); } if (minECSizeExt > 0) { w.WriteLine("Minimum EC size (with extension): {0}", minECSizeExt); if (minECSize == 0) { w.WriteLine("Server does not use EC without" + " the client extension"); } } if (minECSize > 0 || minECSizeExt > 0) { w.WriteLine("ECDH parameter reuse: {0}", kxReuseECDH ? "yes" : " no"); } if (namedCurves != null && namedCurves.Length > 0) { w.WriteLine("Supported curves (size and name)" + " ('*' = selected by server):"); foreach (SSLCurve nc in namedCurves) { w.WriteLine(" {0} {1,3} {2}", IsSpontaneous(nc) ? "*" : " ", nc.Size, nc.Name); } if (curveExplicitPrime > 0) { w.WriteLine(" explicit prime, size = {0}", curveExplicitPrime); } if (curveExplicitChar2 > 0) { w.WriteLine(" explicit char2, size = {0}", curveExplicitChar2); } } w.WriteLine("========================================="); if (warnings == null) { Analyse(); } if (warnings.Count == 0) { w.WriteLine("No warning."); } else { foreach (string k in warnings.Keys) { w.WriteLine("WARN[{0}]: {1}", k, warnings[k]); } } }
/* * Encode the report as JSON. */ internal void Print(JSON js) { js.OpenInit(false); js.AddPair("connectionName", connName); js.AddPair("connectionPort", connPort); js.AddPair("SNI", sni); if (ssl2Suites != null && ssl2Suites.Length > 0) { js.OpenPairObject("SSLv2"); js.OpenPairArray("suites"); foreach (int s in ssl2Suites) { js.OpenElementObject(); js.AddPair("id", s); js.AddPair("name", CipherSuite.ToNameV2(s)); js.Close(); } js.Close(); js.Close(); } foreach (int v in suites.Keys) { js.OpenPairObject(M.VersionString(v)); SupportedCipherSuites scs = suites[v]; string sel; if (scs.PrefClient) { sel = "client"; } else if (scs.PrefServer) { sel = "server"; } else { sel = "complex"; } js.AddPair("suiteSelection", sel); js.OpenPairArray("suites"); foreach (int s in scs.Suites) { js.OpenElementObject(); js.AddPair("id", s); js.AddPair("name", CipherSuite.ToName(s)); CipherSuite cs; if (CipherSuite.ALL.TryGetValue(s, out cs)) { js.AddPair("strength", cs.Strength); js.AddPair("forwardSecrecy", cs.HasForwardSecrecy); js.AddPair("anonymous", cs.IsAnonymous); js.AddPair("serverKeyType", cs.ServerKeyType); } js.Close(); } js.Close(); js.Close(); } if (ssl2Chain != null) { js.OpenPairObject("ssl2Cert"); PrintCert(js, ssl2Chain, 0); js.Close(); } js.OpenPairArray("ssl3Chains"); foreach (X509Chain xchain in chains.Values) { js.OpenElementObject(); int n = xchain.Elements.Length; js.AddPair("length", n); js.AddPair("decoded", xchain.Decodable); if (xchain.Decodable) { js.AddPair("namesMatch", xchain.NamesMatch); js.AddPair("includesRoot", xchain.IncludesRoot); js.OpenPairArray("signHashes"); foreach (string name in xchain.SignHashes) { js.AddElement(name); } js.Close(); } js.OpenPairArray("certificates"); for (int i = 0; i < n; i++) { js.OpenElementObject(); PrintCert(js, xchain, i); js.Close(); } js.Close(); js.Close(); } js.Close(); js.AddPair("deflateCompress", DeflateCompress); if (serverTimeOffset == Int64.MinValue) { js.AddPair("serverTime", "none"); } else if (serverTimeOffset == Int64.MaxValue) { js.AddPair("serverTime", "random"); } else { DateTime dt = DateTime.UtcNow; dt = dt.AddMilliseconds((double)serverTimeOffset); js.AddPair("serverTime", string.Format( "{0:yyyy-MM-dd HH:mm:ss} UTC", dt)); js.AddPair("serverTimeOffsetMillis", serverTimeOffset); } js.AddPair("secureRenegotiation", doesRenego); js.AddPair("ssl2HelloFormat", helloV2); if (minDHSize > 0) { js.AddPair("minDHSize", minDHSize); js.AddPair("kxReuseDH", kxReuseDH); } if (minECSize > 0) { js.AddPair("minECSize", minECSize); } if (minECSizeExt > 0) { js.AddPair("minECSizeExt", minECSizeExt); } if (minECSize > 0 || minECSizeExt > 0) { js.AddPair("kxReuseECDH", kxReuseECDH); } if ((namedCurves != null && namedCurves.Length > 0) || curveExplicitPrime > 0 || curveExplicitChar2 > 0) { js.OpenPairArray("namedCurves"); foreach (SSLCurve nc in namedCurves) { js.OpenElementObject(); js.AddPair("name", nc.Name); js.AddPair("size", nc.Size); js.AddPair("spontaneous", IsSpontaneous(nc)); js.Close(); } if (curveExplicitPrime > 0) { js.OpenElementObject(); js.AddPair("name", "explicitPrime"); js.AddPair("size", curveExplicitPrime); js.Close(); } if (curveExplicitChar2 > 0) { js.OpenElementObject(); js.AddPair("name", "explicitChar2"); js.AddPair("size", curveExplicitChar2); js.Close(); } js.Close(); } if (warnings == null) { Analyse(); } js.OpenPairArray("warnings"); foreach (string k in warnings.Keys) { js.OpenElementObject(); js.AddPair("id", k); js.AddPair("text", warnings[k]); js.Close(); } js.Close(); js.Close(); }
private void AddServerHelloMessage(OutgoingMessageBag outgoingMessages, CipherSuite[] cipherSuites) { ServerHelloMessage serverHelloMessage = new ServerHelloMessage(); serverHelloMessage.RandomNumber = new byte[RandomNumberLength]; m_rng.GetBytes(serverHelloMessage.RandomNumber); SecurityParameters.ServerRandom = serverHelloMessage.RandomNumber; // in case their is no much the server will return this defaul serverHelloMessage.CipherSuite = CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA; foreach (CipherSuite cipherSuite in cipherSuites) { if (AllowedCipherSuites.Contains(cipherSuite)) { serverHelloMessage.CipherSuite = cipherSuite; SetCipherSuite(cipherSuite); break; } } NetMQMessage outgoingMessage = serverHelloMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ServerHello; }
public static CipherSuite InitializeCipherSuite(byte[] master, byte[] clientrnd, byte[] serverrnd, CipherDefinition definition, ConnectionEnd entity) { CipherSuite ret = new CipherSuite(); SymmetricAlgorithm bulk = (SymmetricAlgorithm)Activator.CreateInstance(definition.BulkCipherAlgorithm); if (definition.BulkIVSize > 0) { bulk.Mode = CipherMode.CBC; } bulk.Padding = PaddingMode.None; bulk.BlockSize = definition.BulkIVSize * 8; // get the keys and IVs byte[] client_mac, server_mac, client_key, server_key, client_iv, server_iv; Ssl3DeriveBytes prf = new Ssl3DeriveBytes(master, clientrnd, serverrnd, false); client_mac = prf.GetBytes(definition.HashSize); server_mac = prf.GetBytes(definition.HashSize); client_key = prf.GetBytes(definition.BulkKeySize); server_key = prf.GetBytes(definition.BulkKeySize); client_iv = prf.GetBytes(definition.BulkIVSize); server_iv = prf.GetBytes(definition.BulkIVSize); prf.Dispose(); if (definition.Exportable) // make some extra modifications if the keys are exportable { MD5 md5 = new MD5CryptoServiceProvider(); md5.TransformBlock(client_key, 0, client_key.Length, client_key, 0); md5.TransformBlock(clientrnd, 0, clientrnd.Length, clientrnd, 0); md5.TransformFinalBlock(serverrnd, 0, serverrnd.Length); client_key = new byte[definition.BulkExpandedSize]; Array.Copy(md5.Hash, 0, client_key, 0, client_key.Length); md5.Initialize(); md5.TransformBlock(server_key, 0, server_key.Length, server_key, 0); md5.TransformBlock(serverrnd, 0, serverrnd.Length, serverrnd, 0); md5.TransformFinalBlock(clientrnd, 0, clientrnd.Length); server_key = new byte[definition.BulkExpandedSize]; Array.Copy(md5.Hash, 0, server_key, 0, server_key.Length); md5.Initialize(); md5.TransformBlock(clientrnd, 0, clientrnd.Length, clientrnd, 0); md5.TransformFinalBlock(serverrnd, 0, serverrnd.Length); client_iv = new byte[definition.BulkIVSize]; Array.Copy(md5.Hash, 0, client_iv, 0, client_iv.Length); md5.Initialize(); md5.TransformBlock(serverrnd, 0, serverrnd.Length, serverrnd, 0); md5.TransformFinalBlock(clientrnd, 0, clientrnd.Length); server_iv = new byte[definition.BulkIVSize]; Array.Copy(md5.Hash, 0, server_iv, 0, server_iv.Length); md5.Clear(); } // generate the cipher objects if (entity == ConnectionEnd.Client) { ret.Encryptor = bulk.CreateEncryptor(client_key, client_iv); ret.Decryptor = bulk.CreateDecryptor(server_key, server_iv); ret.LocalHasher = new Ssl3RecordMAC(definition.HashAlgorithmType, client_mac); ret.RemoteHasher = new Ssl3RecordMAC(definition.HashAlgorithmType, server_mac); } else { ret.Encryptor = bulk.CreateEncryptor(server_key, server_iv); ret.Decryptor = bulk.CreateDecryptor(client_key, client_iv); ret.LocalHasher = new Ssl3RecordMAC(definition.HashAlgorithmType, server_mac); ret.RemoteHasher = new Ssl3RecordMAC(definition.HashAlgorithmType, client_mac); } // clear sensitive data Array.Clear(client_mac, 0, client_mac.Length); Array.Clear(server_mac, 0, server_mac.Length); Array.Clear(client_key, 0, client_key.Length); Array.Clear(server_key, 0, server_key.Length); Array.Clear(client_iv, 0, client_iv.Length); Array.Clear(server_iv, 0, server_iv.Length); return(ret); }
public MyGaloisCounterCipher(bool isServer, TlsProtocolCode protocol, CipherSuite cipher, byte[] iv) : base(isServer, protocol, cipher) { this.iv = iv; }
private static bool ArrayContains(CipherSuite[] a, CipherSuite n) { for (int i = 0; i < a.Length; ++i) { if (a[i] == n) return true; } return false; }
public static void UpdateReportAggregator(ReportAggregator aggregator, Report report) { String serverUnderTest = $"{report.ConnName}:{report.ConnPort}"; if (report.SSLv2Chain != null) { aggregator.AddSsl2Cert(serverUnderTest, report.SSLv2Chain); X509Cert xc = report.SSLv2Chain.ElementsRev[0]; if (xc != null && xc.ValidTo.CompareTo(DateTime.Now) < 0) { aggregator.AddOverduedCertificate(serverUnderTest, xc.ValidTo); } } if (report.ssl2Suites != null && report.ssl2Suites.Length > 0) { aggregator.AddSuportedSslVersion(M.VersionString(M.SSLv20)); foreach (int s in report.ssl2Suites) { aggregator.AddSupportedCipherSuite(CipherSuite.ToNameV2(s)); } } aggregator.AddSsl3Certs(serverUnderTest, report.chains.Values); InspectCerts(aggregator, report, serverUnderTest); foreach (int v in report.suites.Keys) { aggregator.AddSuportedSslVersion(M.VersionString(v)); SupportedCipherSuites scs = report.suites[v]; if (scs.PrefClient) { aggregator.AddCipherSuiteSelectionMode("uses client preferences"); } else if (scs.PrefServer) { aggregator.AddCipherSuiteSelectionMode("enforce server preferences"); } else { aggregator.AddCipherSuiteSelectionMode("complex"); } foreach (int s in scs.Suites) { CipherSuite cs; string strength; string fsf; string anon; string kt; if (CipherSuite.ALL.TryGetValue(s, out cs)) { strength = cs.Strength.ToString(); fsf = cs.HasForwardSecrecy ? "f" : "-"; anon = cs.IsAnonymous ? "A" : "-"; kt = cs.ServerKeyType; } else { strength = "?"; fsf = "?"; anon = "?"; kt = "?"; } aggregator.AddSupportedCipherSuite($"{strength}{fsf}{anon} (key: {kt,4}) {CipherSuite.ToName(s)}"); } } foreach (var warning in report.Warnings) { aggregator.AddWarning(warning.Value); } }