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); } }
// TODO Refactor around ServerECDHParams before making this public internal static ECPrivateKeyParameters GenerateEphemeralServerKeyExchange(SecureRandom random, int[] namedCurves, byte[] ecPointFormats, Stream output) { /* First we try to find a supported named curve from the client's list. */ int namedCurve = -1; if (namedCurves == null) { // TODO Let the peer choose the default named curve namedCurve = NamedCurve.secp256r1; } else { for (int i = 0; i < namedCurves.Length; ++i) { int entry = namedCurves[i]; if (NamedCurve.IsValid(entry) && IsSupportedNamedCurve(entry)) { namedCurve = entry; break; } } } ECDomainParameters ecParams = null; if (namedCurve >= 0) { ecParams = GetParametersForNamedCurve(namedCurve); } else { /* If no named curves are suitable, check if the client supports explicit curves. */ if (Arrays.Contains(namedCurves, NamedCurve.arbitrary_explicit_prime_curves)) { ecParams = GetParametersForNamedCurve(NamedCurve.secp256r1); } else if (Arrays.Contains(namedCurves, NamedCurve.arbitrary_explicit_char2_curves)) { ecParams = GetParametersForNamedCurve(NamedCurve.sect283r1); } } if (ecParams == null) { /* * NOTE: We shouldn't have negotiated ECDHE key exchange since we apparently can't find * a suitable curve. */ throw new TlsFatalAlert(AlertDescription.internal_error); } if (namedCurve < 0) { WriteExplicitECParameters(ecPointFormats, ecParams, output); } else { WriteNamedECParameters(namedCurve, output); } return(GenerateEphemeralClientKeyExchange(random, ecPointFormats, ecParams, output)); }