Esempio n. 1
0
    void ParseServerKeyExchangeInner(HMParser hm)
    {
        CipherSuite cs;

        if (!CipherSuite.ALL.TryGetValue(selectedCipherSuite, out cs))
        {
            unknownSKE = true;
            hm.Close(true);
            return;
        }
        if (cs.IsDHE)
        {
            /*
             * If this is DHE_PSK, then there is first a
             * "key hint" to skip.
             */
            if (cs.IsPSK)
            {
                hm.ReadBlobVar(2);
            }

            /*
             * DH parameters: p, g, y. We are only interested
             * in p.
             */
            byte[] p = hm.ReadBlobVar(2);
            dhSize = M.BitLength(p);
            hm.ReadBlobVar(2);
            hm.ReadBlobVar(2);
            if (cs.ServerKeyType != "none")
            {
                if (version >= M.TLSv12)
                {
                    /*
                     * Hash-and-sign identifiers.
                     */
                    hm.Read2();
                }
                hm.ReadBlobVar(2);
            }
        }
        else if (cs.IsECDHE)
        {
            /*
             * If this is ECDHE_PSK, then there is first a
             * "key hint" to skip.
             */
            if (cs.IsPSK)
            {
                hm.ReadBlobVar(2);
            }

            /*
             * Read curve type: one byte.
             */
            switch (hm.Read1())
            {
            case 1:
                /*
                 * explicit_prime: p, a, b, G,
                 * order, cofactor.
                 */
                hm.ReadBlobVar(1);
                hm.ReadBlobVar(1);
                hm.ReadBlobVar(1);
                hm.ReadBlobVar(1);
                ecSize = M.AdjustedBitLength(hm.ReadBlobVar(1));
                hm.ReadBlobVar(1);
                curveExplicitPrime = true;
                break;

            case 2:
                /* explicit_char2 */
                hm.Read2();
                switch (hm.Read1())
                {
                case 1:
                    /* trinomial */
                    hm.ReadBlobVar(1);
                    break;

                case 2:
                    /* pentanomial */
                    hm.ReadBlobVar(1);
                    hm.ReadBlobVar(1);
                    hm.ReadBlobVar(1);
                    break;

                default:
                    hm.Close(true);
                    unknownSKE = true;
                    return;
                }
                hm.ReadBlobVar(1);
                hm.ReadBlobVar(1);
                hm.ReadBlobVar(1);
                ecSize = M.AdjustedBitLength(hm.ReadBlobVar(1));
                hm.ReadBlobVar(1);
                curveExplicitChar2 = true;
                break;

            case 3:
                /*
                 * named_curve.
                 */
                int id = hm.Read2();
                if (SSLCurve.ALL.TryGetValue(id, out curve))
                {
                    ecSize = curve.Size;
                }
                else
                {
                    curve = null;
                    hm.Close(true);
                    unknownSKE = true;
                    return;
                }
                break;

            default:
                hm.Close(true);
                unknownSKE = true;
                return;
            }

            /*
             * Read public key: one curve point.
             */
            hm.ReadBlobVar(1);
            if (cs.ServerKeyType != "none")
            {
                if (version >= M.TLSv12)
                {
                    /*
                     * Hash-and-sign identifiers.
                     */
                    hm.Read2();
                }
                hm.ReadBlobVar(2);
            }
        }
        else if (cs.IsRSAExport)
        {
            /*
             * If cipher suite uses RSA key exchange and is
             * flagged "export" then it may send an ephemeral
             * RSA key pair, which will be weak and probably
             * not very ephemeral, since RSA key pair generation
             * is kinda expensive.
             *
             * Format: modulus, public exponent, signature.
             */
            hm.ReadBlobVar(2);
            hm.ReadBlobVar(2);
            if (version >= M.TLSv12)
            {
                /*
                 * Hash-and-sign identifiers.
                 */
                hm.Read2();
            }
            hm.ReadBlobVar(2);
        }
        else if (cs.IsSRP)
        {
            /*
             * SRP parameters are: N, g, s, B. N is the
             * modulus.
             */
            dhSize = M.BitLength(hm.ReadBlobVar(2));
            hm.ReadBlobVar(2);
            hm.ReadBlobVar(1);
            hm.ReadBlobVar(2);

            /*
             * RFC 5054 says that there is a signature,
             * except if the server sent no certificate. What
             * happens at the encoding level is unclear, so
             * we skip the remaining bytes.
             */
            hm.SkipRemainder();
        }
        else if (cs.IsPSK)
        {
            /*
             * Key hint from the server.
             */
            hm.ReadBlobVar(2);
        }
        else
        {
            throw new IOException("Unexpected ServerKeyExchange");
        }
        hm.Close();
    }
Esempio n. 2
0
    /*
     * Parse messages from the server: from ServerHello to
     * ServerHelloDone.
     */
    internal void Parse(SSLRecord rec)
    {
        rec.SetExpectedType(M.HANDSHAKE);

        /*
         * First parse a ServerHello.
         */
        HMParser sh = new HMParser(rec);

        if (sh.MessageType != M.SERVER_HELLO)
        {
            throw new Exception("Not a ServerHello");
        }
        version = sh.Read2();
        byte[] serverRandom = sh.ReadBlobFixed(32);
        timeMillis = 1000 * (long)M.Dec32be(serverRandom, 0);
        sessionID  = sh.ReadBlobVar(1);
        if (sessionID.Length > 32)
        {
            throw new Exception("Oversized session ID");
        }
        selectedCipherSuite = sh.Read2();
        int cm = sh.Read1();

        if (cm == 0)
        {
            deflateCompress = false;
        }
        else if (cm == 1)
        {
            deflateCompress = true;
        }
        else
        {
            throw new Exception(
                      "Unknown compression method: " + cm);
        }
        if (!sh.EndOfStruct)
        {
            sh.OpenVar(2);
            Dictionary <int, bool> d = new Dictionary <int, bool>();
            while (!sh.EndOfStruct)
            {
                int extType = sh.Read2();
                if (d.ContainsKey(extType))
                {
                    throw new Exception(
                              "Duplicate extension: "
                              + extType);
                }
                d[extType] = true;
                sh.OpenVar(2);
                switch (extType)
                {
                case M.EXT_SERVER_NAME:
                    ParseEmptyServerName(sh);
                    break;

                case M.EXT_RENEGOTIATION_INFO:
                    ParseRenegInfo(sh);
                    break;

                case M.EXT_SUPPORTED_CURVES:
                    ParseSupportedCurves(sh);
                    break;

                case M.EXT_SUPPORTED_EC_POINTS:
                    ParseSupportedECPoints(sh);
                    break;

                default:
                    throw new Exception(
                              "Unknown extension: "
                              + extType);
                }
                sh.Close();
            }
            sh.Close();
        }
        sh.Close();

        /*
         * Read other messages, up to the ServerHelloDone.
         */
        try {
            bool seenSHD = false;
            while (!seenSHD)
            {
                HMParser hm = new HMParser(rec);
                switch (hm.MessageType)
                {
                case M.CERTIFICATE:
                    ParseCertificate(hm);
                    break;

                case M.SERVER_KEY_EXCHANGE:
                    ParseServerKeyExchange(hm);
                    break;

                case M.CERTIFICATE_REQUEST:
                    ParseCertificateRequest(hm);
                    break;

                case M.SERVER_HELLO_DONE:
                    hm.Close();
                    seenSHD = true;
                    break;

                default:
                    hm.Close(true);
                    break;
                }
            }
        } catch {
            failedAfterHello = true;
        }

        recordVersion = rec.GetInVersion();
    }