public override void ProcessServerKeyExchange(Stream input) { SecurityParameters securityParameters = mContext.SecurityParameters; SignerInputBuffer buf = new SignerInputBuffer(); Stream teeIn = new TeeInputStream(input, buf); ECDomainParameters curveParams = TlsEccUtilities.ReadECParameters(mNamedCurves, mClientECPointFormats, teeIn); byte[] point = TlsUtilities.ReadOpaque8(teeIn); DigitallySigned signedParams = ParseSignature(input); mSignatureAndHashAlgorithm = signedParams.Algorithm; ISigner signer = InitVerifyer(mTlsSigner, signedParams.Algorithm, securityParameters); buf.UpdateSigner(signer); if (!signer.VerifySignature(signedParams.Signature)) { throw new TlsFatalAlert(AlertDescription.decrypt_error); } mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey( mClientECPointFormats, curveParams, point)); }
public override void ProcessClientKeyExchange(Stream input) { byte[] array = TlsUtilities.ReadOpaque16(input); mPsk = mPskIdentityManager.GetPsk(array); if (mPsk == null) { throw new TlsFatalAlert(115); } mContext.SecurityParameters.pskIdentity = array; if (mKeyExchange == 14) { BigInteger y = TlsDHUtilities.ReadDHParameter(input); mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(y, mDHParameters)); } else if (mKeyExchange == 24) { byte[] encoding = TlsUtilities.ReadOpaque8(input); ECDomainParameters parameters = mECAgreePrivateKey.Parameters; mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(mServerECPointFormats, parameters, encoding)); } else if (mKeyExchange == 15) { byte[] encryptedPreMasterSecret = (!TlsUtilities.IsSsl(mContext)) ? TlsUtilities.ReadOpaque16(input) : Streams.ReadAll(input); mPremasterSecret = mServerCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret); } }
protected virtual byte[] ProcessHelloVerifyRequest(ClientHandshakeState state, byte[] body) { MemoryStream buf = new MemoryStream(body, false); ProtocolVersion server_version = TlsUtilities.ReadVersion(buf); byte[] cookie = TlsUtilities.ReadOpaque8(buf); TlsProtocol.AssertEmpty(buf); // TODO Seems this behaviour is not yet in line with OpenSSL for DTLS 1.2 // reportServerVersion(state, server_version); if (!server_version.IsEqualOrEarlierVersionOf(state.clientContext.ClientVersion)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } /* * RFC 6347 This specification increases the cookie size limit to 255 bytes for greater * future flexibility. The limit remains 32 for previous versions of DTLS. */ if (!ProtocolVersion.DTLSv12.IsEqualOrEarlierVersionOf(server_version) && cookie.Length > 32) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } return(cookie); }
public static UseSrtpData ReadUseSrtpExtension(byte[] extensionData) { if (extensionData == null) { throw new ArgumentNullException("extensionData"); } MemoryStream buf = new MemoryStream(extensionData, true); // SRTPProtectionProfiles int length = TlsUtilities.ReadUint16(buf); if (length < 2 || (length & 1) != 0) { throw new TlsFatalAlert(AlertDescription.decode_error); } int[] protectionProfiles = TlsUtilities.ReadUint16Array(length / 2, buf); // srtp_mki byte[] mki = TlsUtilities.ReadOpaque8(buf); TlsProtocol.AssertEmpty(buf); return(new UseSrtpData(protectionProfiles, mki)); }
public override void ProcessClientKeyExchange(Stream input) { if (mECAgreePublicKey == null) { byte[] encoding = TlsUtilities.ReadOpaque8(input); ECDomainParameters parameters = mECAgreePrivateKey.Parameters; mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(mServerECPointFormats, parameters, encoding)); } }
protected virtual void ReceiveClientHelloMessage(MemoryStream buf) { ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(buf); mRecordStream.SetWriteVersion(protocolVersion); if (protocolVersion.IsDtls) { throw new TlsFatalAlert(47); } byte[] clientRandom = TlsUtilities.ReadFully(32, buf); byte[] array = TlsUtilities.ReadOpaque8(buf); if (array.Length > 32) { throw new TlsFatalAlert(47); } int num = TlsUtilities.ReadUint16(buf); if (num < 2 || (num & 1) != 0) { throw new TlsFatalAlert(50); } mOfferedCipherSuites = TlsUtilities.ReadUint16Array(num / 2, buf); int num2 = TlsUtilities.ReadUint8(buf); if (num2 < 1) { throw new TlsFatalAlert(47); } mOfferedCompressionMethods = TlsUtilities.ReadUint8Array(num2, buf); mClientExtensions = TlsProtocol.ReadExtensions(buf); mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mClientExtensions); ContextAdmin.SetClientVersion(protocolVersion); mTlsServer.NotifyClientVersion(protocolVersion); mTlsServer.NotifyFallback(Arrays.Contains(mOfferedCipherSuites, 22016)); mSecurityParameters.clientRandom = clientRandom; mTlsServer.NotifyOfferedCipherSuites(mOfferedCipherSuites); mTlsServer.NotifyOfferedCompressionMethods(mOfferedCompressionMethods); if (Arrays.Contains(mOfferedCipherSuites, 255)) { mSecureRenegotiation = true; } byte[] extensionData = TlsUtilities.GetExtensionData(mClientExtensions, 65281); if (extensionData != null) { mSecureRenegotiation = true; if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(40); } } mTlsServer.NotifySecureRenegotiation(mSecureRenegotiation); if (mClientExtensions != null) { mTlsServer.ProcessClientExtensions(mClientExtensions); } }
public ECPublicKeyParameters DeserializeECPublicKey(byte[] publicKey) { using var memoryStream = new MemoryStream(publicKey); return(TlsEccUtilities.ValidateECPublicKey( TlsEccUtilities.DeserializeECPublicKey( _ecPointFormats, _ecParameters, TlsUtilities.ReadOpaque8(memoryStream) ) )); }
/** * Parse a {@link ServerSRPParams} from an {@link InputStream}. * * @param input * the {@link InputStream} to parse from. * @return a {@link ServerSRPParams} object. * @throws IOException */ public static ServerSrpParams Parse(Stream input) { BigInteger N = TlsSrpUtilities.ReadSrpParameter(input); BigInteger g = TlsSrpUtilities.ReadSrpParameter(input); byte[] s = TlsUtilities.ReadOpaque8(input); BigInteger B = TlsSrpUtilities.ReadSrpParameter(input); return(new ServerSrpParams(N, g, s, B)); }
public static byte[] ReadSrpExtension(byte[] extensionData) { if (extensionData == null) { throw new ArgumentNullException("extensionData"); } MemoryStream memoryStream = new MemoryStream(extensionData, writable: false); byte[] result = TlsUtilities.ReadOpaque8(memoryStream); TlsProtocol.AssertEmpty(memoryStream); return(result); }
public static byte[] ReadSrpExtension(byte[] extensionData) { if (extensionData == null) { throw new ArgumentNullException("extensionData"); } MemoryStream buf = new MemoryStream(extensionData, false); byte[] identity = TlsUtilities.ReadOpaque8(buf); TlsProtocol.AssertEmpty(buf); return(identity); }
public override void ProcessClientKeyExchange(Stream input) { if (mECAgreePublicKey != null) { // For ecdsa_fixed_ecdh and rsa_fixed_ecdh, the key arrived in the client certificate return; } byte[] point = TlsUtilities.ReadOpaque8(input); ECDomainParameters curve_params = this.mECAgreePrivateKey.Parameters; this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey( mServerECPointFormats, curve_params, point)); }
public override void ProcessServerKeyExchange(Stream input) { mPskIdentityHint = TlsUtilities.ReadOpaque16(input); if (mKeyExchange == 14) { ServerDHParams serverDHParams = ServerDHParams.Parse(input); mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(serverDHParams.PublicKey); mDHParameters = mDHAgreePublicKey.Parameters; } else if (mKeyExchange == 24) { ECDomainParameters curve_params = TlsEccUtilities.ReadECParameters(mNamedCurves, mClientECPointFormats, input); byte[] encoding = TlsUtilities.ReadOpaque8(input); mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(mClientECPointFormats, curve_params, encoding)); } }
public override void ProcessServerKeyExchange(Stream input) { if (!RequiresServerKeyExchange) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } // ECDH_anon is handled here, ECDHE_* in a subclass ECDomainParameters curve_params = TlsEccUtilities.ReadECParameters(mNamedCurves, mClientECPointFormats, input); byte[] point = TlsUtilities.ReadOpaque8(input); this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey( mClientECPointFormats, curve_params, point)); }
public virtual void ProcessServerExtensions(IDictionary serverExtensions) { /* * TlsProtocol implementation validates that any server extensions received correspond to * client extensions sent. By default, we don't send any, and this method is not called. */ if (serverExtensions != null) { /* * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension. */ CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.signature_algorithms); CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.supported_groups); if (TlsEccUtilities.IsEccCipherSuite(this.mSelectedCipherSuite)) { this.mServerECPointFormats = TlsEccUtilities.GetSupportedPointFormatsExtension(serverExtensions); } else { CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.ec_point_formats); } /* * RFC 7685 3. The server MUST NOT echo the extension. */ CheckForUnexpectedServerExtension(serverExtensions, ExtensionType.padding); // https://tools.ietf.org/html/rfc7301 byte[] extensionData = TlsUtilities.GetExtensionData(serverExtensions, ExtensionType.application_layer_protocol_negotiation); if (extensionData != null) { using (var exBuf = new MemoryStream(extensionData, false)) { byte[] alpnList = TlsUtilities.ReadOpaque16(exBuf); // the "ProtocolNameList" MUST contain exactly one "ProtocolName" using (var alpnBuf = new MemoryStream(alpnList)) { byte[] asciiBytes = TlsUtilities.ReadOpaque8(alpnBuf); this.ServerSupportedProtocol = Strings.FromAsciiByteArray(asciiBytes); } } } } }
public override void ProcessServerKeyExchange(Stream input) { SecurityParameters securityParameters = mContext.SecurityParameters; SignerInputBuffer signerInputBuffer = new SignerInputBuffer(); Stream input2 = new TeeInputStream(input, signerInputBuffer); ECDomainParameters curve_params = TlsEccUtilities.ReadECParameters(mNamedCurves, mClientECPointFormats, input2); byte[] encoding = TlsUtilities.ReadOpaque8(input2); DigitallySigned digitallySigned = ParseSignature(input); ISigner signer = InitVerifyer(mTlsSigner, digitallySigned.Algorithm, securityParameters); signerInputBuffer.UpdateSigner(signer); if (!signer.VerifySignature(digitallySigned.Signature)) { throw new TlsFatalAlert(51); } mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(mClientECPointFormats, curve_params, encoding)); }
public override void ProcessServerKeyExchange(Stream input) { this.mPskIdentityHint = TlsUtilities.ReadOpaque16(input); if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input); this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters); } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { ECDomainParameters ecParams = TlsEccUtilities.ReadECParameters(mNamedCurves, mClientECPointFormats, input); byte[] point = TlsUtilities.ReadOpaque8(input); this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey( mClientECPointFormats, ecParams, point)); } }
public override void ProcessClientKeyExchange(Stream input) { byte[] psk_identity = TlsUtilities.ReadOpaque16(input); this.mPsk = mPskIdentityManager.GetPsk(psk_identity); if (mPsk == null) { throw new TlsFatalAlert(AlertDescription.unknown_psk_identity); } mContext.SecurityParameters.pskIdentity = psk_identity; if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { BigInteger Yc = TlsDHUtilities.ReadDHParameter(input); this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters)); } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { byte[] point = TlsUtilities.ReadOpaque8(input); ECDomainParameters curve_params = this.mECAgreePrivateKey.Parameters; this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey( mServerECPointFormats, curve_params, point)); } else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK) { byte[] encryptedPreMasterSecret; if (TlsUtilities.IsSsl(mContext)) { // TODO Do any SSLv3 clients actually include the length? encryptedPreMasterSecret = Streams.ReadAll(input); } else { encryptedPreMasterSecret = TlsUtilities.ReadOpaque16(input); } this.mPremasterSecret = mServerCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret); } }
protected virtual void ProcessServerHello(ClientHandshakeState state, byte[] body) { SecurityParameters securityParameters = state.clientContext.SecurityParameters; MemoryStream buf = new MemoryStream(body, false); { ProtocolVersion server_version = TlsUtilities.ReadVersion(buf); ReportServerVersion(state, server_version); } securityParameters.serverRandom = TlsUtilities.ReadFully(32, buf); state.selectedSessionID = TlsUtilities.ReadOpaque8(buf); if (state.selectedSessionID.Length > 32) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } state.client.NotifySessionID(state.selectedSessionID); state.resumedSession = state.selectedSessionID.Length > 0 && state.tlsSession != null && Arrays.AreEqual(state.selectedSessionID, state.tlsSession.SessionID); int selectedCipherSuite = TlsUtilities.ReadUint16(buf); if (!Arrays.Contains(state.offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, state.clientContext.ServerVersion)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } ValidateSelectedCipherSuite(selectedCipherSuite, AlertDescription.illegal_parameter); state.client.NotifySelectedCipherSuite(selectedCipherSuite); byte selectedCompressionMethod = TlsUtilities.ReadUint8(buf); if (CompressionMethod.cls_null != selectedCompressionMethod) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } state.client.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. */ // Integer -> byte[] state.serverExtensions = TlsProtocol.ReadExtensions(buf); /* * RFC 7627 4. Clients and servers SHOULD NOT accept handshakes that do not use the extended * master secret [..]. (and see 5.2, 5.3) */ securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.serverExtensions); if (!securityParameters.IsExtendedMasterSecret && (state.resumedSession || state.client.RequiresExtendedMasterSecret())) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } /* * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an * extended client hello message. However, see RFC 5746 exception below. We always include * the SCSV, so an Extended Server Hello is always allowed. */ if (state.serverExtensions != null) { foreach (int extType in state.serverExtensions.Keys) { /* * RFC 5746 3.6. Note that sending a "renegotiation_info" extension in response to a * ClientHello containing only the SCSV is an explicit exception to the prohibition * in RFC 5246, Section 7.4.1.4, on the server sending unsolicited extensions and is * only allowed because the client is signaling its willingness to receive the * extension via the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. */ if (extType == ExtensionType.renegotiation_info) { continue; } /* * RFC 5246 7.4.1.4 An extension type MUST NOT appear in the ServerHello unless the * same extension type appeared in the corresponding ClientHello. If a client * receives an extension type in ServerHello that it did not request in the * associated ClientHello, it MUST abort the handshake with an unsupported_extension * fatal alert. */ if (null == TlsUtilities.GetExtensionData(state.clientExtensions, extType)) { throw new TlsFatalAlert(AlertDescription.unsupported_extension); } /* * 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[.] */ if (state.resumedSession) { // TODO[compat-gnutls] GnuTLS test server sends server extensions e.g. ec_point_formats // TODO[compat-openssl] OpenSSL test server sends server extensions e.g. ec_point_formats // TODO[compat-polarssl] PolarSSL test server sends server extensions e.g. ec_point_formats //throw new TlsFatalAlert(AlertDescription.illegal_parameter); } } } /* * RFC 5746 3.4. Client Behavior: Initial Handshake */ { /* * When a ServerHello is received, the client MUST check if it includes the * "renegotiation_info" extension: */ byte[] renegExtData = TlsUtilities.GetExtensionData(state.serverExtensions, ExtensionType.renegotiation_info); if (renegExtData != null) { /* * 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). */ state.secure_renegotiation = true; if (!Arrays.ConstantTimeAreEqual(renegExtData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } } } // TODO[compat-gnutls] GnuTLS test server fails to send renegotiation_info extension when resuming state.client.NotifySecureRenegotiation(state.secure_renegotiation); IDictionary sessionClientExtensions = state.clientExtensions, sessionServerExtensions = state.serverExtensions; if (state.resumedSession) { if (selectedCipherSuite != state.sessionParameters.CipherSuite || selectedCompressionMethod != state.sessionParameters.CompressionAlgorithm) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } sessionClientExtensions = null; sessionServerExtensions = state.sessionParameters.ReadServerExtensions(); } securityParameters.cipherSuite = selectedCipherSuite; securityParameters.compressionAlgorithm = selectedCompressionMethod; if (sessionServerExtensions != null && sessionServerExtensions.Count > 0) { { /* * RFC 7366 3. If a server receives an encrypt-then-MAC request extension from a client * and then selects a stream or Authenticated Encryption with Associated Data (AEAD) * ciphersuite, it MUST NOT send an encrypt-then-MAC response extension back to the * client. */ bool serverSentEncryptThenMAC = TlsExtensionsUtilities.HasEncryptThenMacExtension(sessionServerExtensions); if (serverSentEncryptThenMAC && !TlsUtilities.IsBlockCipherSuite(securityParameters.CipherSuite)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } securityParameters.encryptThenMac = serverSentEncryptThenMAC; } securityParameters.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.resumedSession, sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(sessionServerExtensions); /* * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be * sent in a session resumption handshake. */ state.allowCertificateStatus = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.status_request, AlertDescription.illegal_parameter); state.expectSessionTicket = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.session_ticket, AlertDescription.illegal_parameter); } if (sessionClientExtensions != null) { state.client.ProcessServerExtensions(sessionServerExtensions); } securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.clientContext, securityParameters.CipherSuite); /* * RFC 5246 7.4.9. Any cipher suite which does not explicitly specify verify_data_length has * a verify_data_length equal to 12. This includes all existing cipher suites. */ securityParameters.verifyDataLength = 12; }
public static BigInteger ReadECParameter(Stream input) { return(new BigInteger(1, TlsUtilities.ReadOpaque8(input))); }
public static ECDomainParameters ReadECParameters(int[] namedCurves, byte[] ecPointFormats, Stream input) { try { byte curveType = TlsUtilities.ReadUint8(input); switch (curveType) { case ECCurveType.explicit_prime: { CheckNamedCurve(namedCurves, NamedCurve.arbitrary_explicit_prime_curves); BigInteger prime_p = ReadECParameter(input); BigInteger a = ReadECFieldElement(prime_p.BitLength, input); BigInteger b = ReadECFieldElement(prime_p.BitLength, input); byte[] baseEncoding = TlsUtilities.ReadOpaque8(input); BigInteger order = ReadECParameter(input); BigInteger cofactor = ReadECParameter(input); ECCurve curve = new FpCurve(prime_p, a, b, order, cofactor); ECPoint basePoint = DeserializeECPoint(ecPointFormats, curve, baseEncoding); return(new ECDomainParameters(curve, basePoint, order, cofactor)); } case ECCurveType.explicit_char2: { CheckNamedCurve(namedCurves, NamedCurve.arbitrary_explicit_char2_curves); int m = TlsUtilities.ReadUint16(input); byte basis = TlsUtilities.ReadUint8(input); if (!ECBasisType.IsValid(basis)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } int k1 = ReadECExponent(m, input), k2 = -1, k3 = -1; if (basis == ECBasisType.ec_basis_pentanomial) { k2 = ReadECExponent(m, input); k3 = ReadECExponent(m, input); } BigInteger a = ReadECFieldElement(m, input); BigInteger b = ReadECFieldElement(m, input); byte[] baseEncoding = TlsUtilities.ReadOpaque8(input); BigInteger order = ReadECParameter(input); BigInteger cofactor = ReadECParameter(input); ECCurve curve = (basis == ECBasisType.ec_basis_pentanomial) ? new F2mCurve(m, k1, k2, k3, a, b, order, cofactor) : new F2mCurve(m, k1, a, b, order, cofactor); ECPoint basePoint = DeserializeECPoint(ecPointFormats, curve, baseEncoding); return(new ECDomainParameters(curve, basePoint, order, cofactor)); } case ECCurveType.named_curve: { int namedCurve = TlsUtilities.ReadUint16(input); if (!NamedCurve.RefersToASpecificNamedCurve(namedCurve)) { /* * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a * specific curve. Values of NamedCurve that indicate support for a class of * explicitly defined curves are not allowed here [...]. */ throw new TlsFatalAlert(AlertDescription.illegal_parameter); } CheckNamedCurve(namedCurves, namedCurve); return(GetParametersForNamedCurve(namedCurve)); } default: throw new TlsFatalAlert(AlertDescription.illegal_parameter); } } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.illegal_parameter, e); } }
public static BigInteger ReadECParameter(Stream input) { // TODO Are leading zeroes okay here? return(new BigInteger(1, TlsUtilities.ReadOpaque8(input))); }
public static BigInteger ReadECFieldElement(int fieldSize, Stream input) { return(DeserializeECFieldElement(fieldSize, TlsUtilities.ReadOpaque8(input))); }
protected virtual void ProcessClientHello(ServerHandshakeState state, byte[] body) { MemoryStream buf = new MemoryStream(body, false); // TODO Read RFCs for guidance on the expected record layer version number ProtocolVersion client_version = TlsUtilities.ReadVersion(buf); if (!client_version.IsDtls) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } /* * Read the client random */ byte[] client_random = TlsUtilities.ReadFully(32, buf); byte[] sessionID = TlsUtilities.ReadOpaque8(buf); if (sessionID.Length > 32) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } // TODO RFC 4347 has the cookie length restricted to 32, but not in RFC 6347 byte[] cookie = TlsUtilities.ReadOpaque8(buf); int cipher_suites_length = TlsUtilities.ReadUint16(buf); if (cipher_suites_length < 2 || (cipher_suites_length & 1) != 0) { throw new TlsFatalAlert(AlertDescription.decode_error); } /* * NOTE: "If the session_id field is not empty (implying a session resumption request) this * vector must include at least the cipher_suite from that session." */ state.offeredCipherSuites = TlsUtilities.ReadUint16Array(cipher_suites_length / 2, buf); int compression_methods_length = TlsUtilities.ReadUint8(buf); if (compression_methods_length < 1) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } state.offeredCompressionMethods = TlsUtilities.ReadUint8Array(compression_methods_length, buf); /* * 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. */ state.clientExtensions = TlsProtocol.ReadExtensions(buf); TlsServerContextImpl context = state.serverContext; SecurityParameters securityParameters = context.SecurityParameters; /* * TODO[session-hash] * * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes * that do not use the extended master secret [..]. (and see 5.2, 5.3) */ securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.clientExtensions); context.SetClientVersion(client_version); state.server.NotifyClientVersion(client_version); state.server.NotifyFallback(Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV)); securityParameters.clientRandom = client_random; state.server.NotifyOfferedCipherSuites(state.offeredCipherSuites); state.server.NotifyOfferedCompressionMethods(state.offeredCompressionMethods); /* * RFC 5746 3.6. Server Behavior: Initial Handshake */ { /* * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension, * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the * ClientHello. Including both is NOT RECOMMENDED. */ /* * When a ClientHello is received, the server MUST check if it includes the * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag * to TRUE. */ if (Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { state.secure_renegotiation = true; } /* * The server MUST check if the "renegotiation_info" extension is included in the * ClientHello. */ byte[] renegExtData = TlsUtilities.GetExtensionData(state.clientExtensions, ExtensionType.renegotiation_info); if (renegExtData != null) { /* * If the extension is present, set secure_renegotiation flag to TRUE. The * server MUST then verify that the length of the "renegotiated_connection" * field is zero, and if it is not, MUST abort the handshake. */ state.secure_renegotiation = true; if (!Arrays.ConstantTimeAreEqual(renegExtData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } } } state.server.NotifySecureRenegotiation(state.secure_renegotiation); if (state.clientExtensions != null) { state.server.ProcessClientExtensions(state.clientExtensions); } }
public static ECDomainParameters ReadECParameters(int[] namedCurves, byte[] ecPointFormats, Stream input) { try { switch (TlsUtilities.ReadUint8(input)) { case 1: { CheckNamedCurve(namedCurves, 65281); BigInteger bigInteger3 = ReadECParameter(input); BigInteger a2 = ReadECFieldElement(bigInteger3.BitLength, input); BigInteger b3 = ReadECFieldElement(bigInteger3.BitLength, input); byte[] encoding2 = TlsUtilities.ReadOpaque8(input); BigInteger bigInteger4 = ReadECParameter(input); BigInteger bigInteger5 = ReadECParameter(input); ECCurve curve2 = new FpCurve(bigInteger3, a2, b3, bigInteger4, bigInteger5); ECPoint g2 = DeserializeECPoint(ecPointFormats, curve2, encoding2); return(new ECDomainParameters(curve2, g2, bigInteger4, bigInteger5)); } case 2: { CheckNamedCurve(namedCurves, 65282); int num = TlsUtilities.ReadUint16(input); byte b = TlsUtilities.ReadUint8(input); if (!ECBasisType.IsValid(b)) { throw new TlsFatalAlert(47); } int num2 = ReadECExponent(num, input); int k = -1; int k2 = -1; if (b == 2) { k = ReadECExponent(num, input); k2 = ReadECExponent(num, input); } BigInteger a = ReadECFieldElement(num, input); BigInteger b2 = ReadECFieldElement(num, input); byte[] encoding = TlsUtilities.ReadOpaque8(input); BigInteger bigInteger = ReadECParameter(input); BigInteger bigInteger2 = ReadECParameter(input); ECCurve curve = (b == 2) ? new F2mCurve(num, num2, k, k2, a, b2, bigInteger, bigInteger2) : new F2mCurve(num, num2, a, b2, bigInteger, bigInteger2); ECPoint g = DeserializeECPoint(ecPointFormats, curve, encoding); return(new ECDomainParameters(curve, g, bigInteger, bigInteger2)); } case 3: { int namedCurve = TlsUtilities.ReadUint16(input); if (!NamedCurve.RefersToASpecificNamedCurve(namedCurve)) { throw new TlsFatalAlert(47); } CheckNamedCurve(namedCurves, namedCurve); return(GetParametersForNamedCurve(namedCurve)); } default: throw new TlsFatalAlert(47); } } catch (Exception alertCause) { throw new TlsFatalAlert(47, alertCause); } }
protected virtual void ReceiveServerHelloMessage(MemoryStream buf) { { ProtocolVersion server_version = TlsUtilities.ReadVersion(buf); if (server_version.IsDtls) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } // Check that this matches what the server is Sending in the record layer if (!server_version.Equals(this.mRecordStream.ReadVersion)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } ProtocolVersion client_version = Context.ClientVersion; if (!server_version.IsEqualOrEarlierVersionOf(client_version)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } this.mRecordStream.SetWriteVersion(server_version); ContextAdmin.SetServerVersion(server_version); this.mTlsClient.NotifyServerVersion(server_version); if (HTTPManager.Logger.Level <= Loglevels.All) { HTTPManager.Logger.Verbose("TlsClientProtocol", "ReceiveServerHelloMessage server_version: " + server_version.ToString(), this.LoggingContext); } } /* * Read the server random */ this.mSecurityParameters.serverRandom = TlsUtilities.ReadFully(32, buf); this.mSelectedSessionID = TlsUtilities.ReadOpaque8(buf); if (this.mSelectedSessionID.Length > 32) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } this.mTlsClient.NotifySessionID(this.mSelectedSessionID); this.mResumedSession = this.mSelectedSessionID.Length > 0 && this.mTlsSession != null && Arrays.AreEqual(this.mSelectedSessionID, this.mTlsSession.SessionID); /* * Find out which CipherSuite the server has chosen and check that it was one of the offered * ones, and is a valid selection for the negotiated version. */ int selectedCipherSuite = TlsUtilities.ReadUint16(buf); if (!Arrays.Contains(this.mOfferedCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, Context.ServerVersion)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } if (HTTPManager.Logger.Level <= Loglevels.All) { HTTPManager.Logger.Verbose("TlsClientProtocol", "ReceiveServerHelloMessage selectedCipherSuite: " + selectedCipherSuite.ToString("X"), this.LoggingContext); } this.mTlsClient.NotifySelectedCipherSuite(selectedCipherSuite); /* * Find out which CompressionMethod the server has chosen and check that it was one of the * offered ones. */ byte selectedCompressionMethod = TlsUtilities.ReadUint8(buf); if (!Arrays.Contains(this.mOfferedCompressionMethods, selectedCompressionMethod)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } if (HTTPManager.Logger.Level <= Loglevels.All) { HTTPManager.Logger.Verbose("TlsClientProtocol", "ReceiveServerHelloMessage selectedCompressionMethod: " + selectedCompressionMethod.ToString(), this.LoggingContext); } this.mTlsClient.NotifySelectedCompressionMethod(selectedCompressionMethod); /* * RFC 3546 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. */ this.mServerExtensions = ReadExtensions(buf); /* * RFC 7627 4. Clients and servers SHOULD NOT accept handshakes that do not use the extended * master secret [..]. (and see 5.2, 5.3) */ this.mSecurityParameters.extendedMasterSecret = !TlsUtilities.IsSsl(mTlsClientContext) && TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mServerExtensions); if (!mSecurityParameters.IsExtendedMasterSecret && (mResumedSession || mTlsClient.RequiresExtendedMasterSecret())) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } /* * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an * extended client hello message. * * However, see RFC 5746 exception below. We always include the SCSV, so an Extended Server * Hello is always allowed. */ if (this.mServerExtensions != null) { foreach (int extType in this.mServerExtensions.Keys) { /* * RFC 5746 3.6. Note that Sending a "renegotiation_info" extension in response to a * ClientHello containing only the SCSV is an explicit exception to the prohibition * in RFC 5246, Section 7.4.1.4, on the server Sending unsolicited extensions and is * only allowed because the client is signaling its willingness to receive the * extension via the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. */ if (extType == ExtensionType.renegotiation_info) { continue; } /* * RFC 5246 7.4.1.4 An extension type MUST NOT appear in the ServerHello unless the * same extension type appeared in the corresponding ClientHello. If a client * receives an extension type in ServerHello that it did not request in the * associated ClientHello, it MUST abort the handshake with an unsupported_extension * fatal alert. */ if (null == TlsUtilities.GetExtensionData(this.mClientExtensions, extType)) { throw new TlsFatalAlert(AlertDescription.unsupported_extension); } /* * 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[.] */ if (this.mResumedSession) { // TODO[compat-gnutls] GnuTLS test server Sends server extensions e.g. ec_point_formats // TODO[compat-openssl] OpenSSL test server Sends server extensions e.g. ec_point_formats // TODO[compat-polarssl] PolarSSL test server Sends server extensions e.g. ec_point_formats // throw new TlsFatalAlert(AlertDescription.illegal_parameter); } if (HTTPManager.Logger.Level <= Loglevels.All) { HTTPManager.Logger.Verbose("TlsClientProtocol", "ReceiveServerHelloMessage mServerExtensions: " + extType.ToString(), this.LoggingContext); } } } /* * RFC 5746 3.4. Client Behavior: Initial Handshake */ { /* * When a ServerHello is received, the client MUST check if it includes the * "renegotiation_info" extension: */ byte[] renegExtData = TlsUtilities.GetExtensionData(this.mServerExtensions, ExtensionType.renegotiation_info); if (renegExtData != null) { /* * 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). */ this.mSecureRenegotiation = true; if (!Arrays.ConstantTimeAreEqual(renegExtData, CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } } } // TODO[compat-gnutls] GnuTLS test server fails to Send renegotiation_info extension when resuming this.mTlsClient.NotifySecureRenegotiation(this.mSecureRenegotiation); IDictionary sessionClientExtensions = mClientExtensions, sessionServerExtensions = mServerExtensions; if (this.mResumedSession) { if (selectedCipherSuite != this.mSessionParameters.CipherSuite || selectedCompressionMethod != this.mSessionParameters.CompressionAlgorithm) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } sessionClientExtensions = null; sessionServerExtensions = this.mSessionParameters.ReadServerExtensions(); } this.mSecurityParameters.cipherSuite = selectedCipherSuite; this.mSecurityParameters.compressionAlgorithm = selectedCompressionMethod; if (sessionServerExtensions != null && sessionServerExtensions.Count > 0) { { /* * RFC 7366 3. If a server receives an encrypt-then-MAC request extension from a client * and then selects a stream or Authenticated Encryption with Associated Data (AEAD) * ciphersuite, it MUST NOT send an encrypt-then-MAC response extension back to the * client. */ bool serverSentEncryptThenMAC = TlsExtensionsUtilities.HasEncryptThenMacExtension(sessionServerExtensions); if (serverSentEncryptThenMAC && !TlsUtilities.IsBlockCipherSuite(selectedCipherSuite)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } this.mSecurityParameters.encryptThenMac = serverSentEncryptThenMAC; } this.mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); this.mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(sessionServerExtensions); /* * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in * a session resumption handshake. */ this.mAllowCertificateStatus = !this.mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.status_request, AlertDescription.illegal_parameter); this.mExpectSessionTicket = !this.mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.session_ticket, AlertDescription.illegal_parameter); } if (sessionClientExtensions != null) { this.mTlsClient.ProcessServerExtensions(sessionServerExtensions); } this.mSecurityParameters.prfAlgorithm = GetPrfAlgorithm(Context, this.mSecurityParameters.CipherSuite); /* * RFC 5246 7.4.9. Any cipher suite which does not explicitly specify * verify_data_length has a verify_data_length equal to 12. This includes all * existing cipher suites. */ this.mSecurityParameters.verifyDataLength = 12; }
protected virtual void ReceiveClientHelloMessage(MemoryStream buf) { ProtocolVersion client_version = TlsUtilities.ReadVersion(buf); mRecordStream.SetWriteVersion(client_version); if (client_version.IsDtls) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } byte[] client_random = TlsUtilities.ReadFully(32, buf); /* * TODO RFC 5077 3.4. If a ticket is presented by the client, the server MUST NOT attempt to * use the Session ID in the ClientHello for stateful session resumption. */ byte[] sessionID = TlsUtilities.ReadOpaque8(buf); if (sessionID.Length > 32) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } /* * TODO RFC 5246 7.4.1.2. If the session_id field is not empty (implying a session * resumption request), this vector MUST include at least the cipher_suite from that * session. */ int cipher_suites_length = TlsUtilities.ReadUint16(buf); if (cipher_suites_length < 2 || (cipher_suites_length & 1) != 0) { throw new TlsFatalAlert(AlertDescription.decode_error); } this.mOfferedCipherSuites = TlsUtilities.ReadUint16Array(cipher_suites_length / 2, buf); /* * TODO RFC 5246 7.4.1.2. If the session_id field is not empty (implying a session * resumption request), it MUST include the compression_method from that session. */ int compression_methods_length = TlsUtilities.ReadUint8(buf); if (compression_methods_length < 1) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } this.mOfferedCompressionMethods = TlsUtilities.ReadUint8Array(compression_methods_length, buf); /* * 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. */ this.mClientExtensions = ReadExtensions(buf); /* * TODO[resumption] Check RFC 7627 5.4. for required behaviour */ /* * RFC 7627 4. Clients and servers SHOULD NOT accept handshakes that do not use the extended * master secret [..]. (and see 5.2, 5.3) */ this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mClientExtensions); if (!mSecurityParameters.IsExtendedMasterSecret && mTlsServer.RequiresExtendedMasterSecret()) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } ContextAdmin.SetClientVersion(client_version); mTlsServer.NotifyClientVersion(client_version); mTlsServer.NotifyFallback(Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_FALLBACK_SCSV)); mSecurityParameters.clientRandom = client_random; mTlsServer.NotifyOfferedCipherSuites(mOfferedCipherSuites); mTlsServer.NotifyOfferedCompressionMethods(mOfferedCompressionMethods); /* * RFC 5746 3.6. Server Behavior: Initial Handshake */ { /* * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension, * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the * ClientHello. Including both is NOT RECOMMENDED. */ /* * When a ClientHello is received, the server MUST check if it includes the * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag * to TRUE. */ if (Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { this.mSecureRenegotiation = true; } /* * The server MUST check if the "renegotiation_info" extension is included in the * ClientHello. */ byte[] renegExtData = TlsUtilities.GetExtensionData(mClientExtensions, ExtensionType.renegotiation_info); if (renegExtData != null) { /* * If the extension is present, set secure_renegotiation flag to TRUE. The * server MUST then verify that the length of the "renegotiated_connection" * field is zero, and if it is not, MUST abort the handshake. */ this.mSecureRenegotiation = true; if (!Arrays.ConstantTimeAreEqual(renegExtData, CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } } } mTlsServer.NotifySecureRenegotiation(this.mSecureRenegotiation); if (mClientExtensions != null) { // NOTE: Validates the padding extension data, if present TlsExtensionsUtilities.GetPaddingExtension(mClientExtensions); mTlsServer.ProcessClientExtensions(mClientExtensions); } }