Ejemplo n.º 1
0
class SSLv2ClientCertificate(_SSLv2Handshake):
    """
    SSLv2 ClientCertificate.
    """
    name = "SSLv2 Handshake - Client Certificate"
    fields_desc = [ByteEnumField("msgtype", 8, _sslv2_handshake_type),

                   ByteEnumField("certtype", 1, {1: "x509_cert"}),
                   FieldLenField("certlen", None, fmt="!H",
                                 length_of="certdata"),
                   FieldLenField("responselen", None, fmt="!H",
                                 length_of="responsedata"),

                   _SSLv2CertDataField("certdata", b"",
                                       length_from=lambda pkt: pkt.certlen),
                   _TLSSignatureField("responsedata", None,
                                      length_from=lambda pkt: pkt.responselen)]

    def build(self, *args, **kargs):
        s = self.tls_session
        sig = self.getfieldval("responsedata")
        test = (sig is None and
                s.sslv2_key_material is not None and
                s.sslv2_challenge_clientcert is not None and
                len(s.server_certs) > 0)
        if test:
            s = self.tls_session
            m = (s.sslv2_key_material +
                 s.sslv2_challenge_clientcert +
                 s.server_certs[0].der)
            self.responsedata = _TLSSignature(tls_session=s)
            self.responsedata._update_sig(m, s.client_key)
        else:
            self.responsedata = b""
        return super(SSLv2ClientCertificate, self).build(*args, **kargs)

    def post_dissection_tls_session_update(self, msg_str):
        self.tls_session_update(msg_str)

        s = self.tls_session
        test = (len(s.client_certs) > 0 and
                s.sslv2_key_material is not None and
                s.sslv2_challenge_clientcert is not None and
                len(s.server_certs) > 0)
        if test:
            m = (s.sslv2_key_material +
                 s.sslv2_challenge_clientcert +
                 s.server_certs[0].der)
            sig_test = self.responsedata._verify_sig(m, s.client_certs[0])
            if not sig_test:
                pkt_info = self.firstlayer().summary()
                log_runtime.info("TLS: invalid client CertificateVerify signature [%s]", pkt_info)

    def tls_session_update(self, msg_str):
        super(SSLv2ClientCertificate, self).tls_session_update(msg_str)
        if self.certdata:
            self.tls_session.client_certs = [self.certdata]
Ejemplo n.º 2
0
class TLSCertificateVerify(_TLSHandshake):
    name = "TLS Handshake - Certificate Verify"
    fields_desc = [
        ByteEnumField("msgtype", 15, _tls_handshake_type),
        ThreeBytesField("msglen", None),
        _TLSSignatureField("sig", None, length_from=lambda pkt: pkt.msglen)
    ]

    def build(self, *args, **kargs):
        sig = self.getfieldval("sig")
        if sig is None:
            s = self.tls_session
            m = "".join(s.handshake_messages)
            if s.tls_version >= 0x0304:
                if s.connection_end == "client":
                    context_string = "TLS 1.3, client CertificateVerify"
                elif s.connection_end == "server":
                    context_string = "TLS 1.3, server CertificateVerify"
                m = b"\x20" * 64 + context_string + b"\x00" + s.wcs.hash.digest(
                    m)
            self.sig = _TLSSignature(tls_session=s)
            if s.connection_end == "client":
                self.sig._update_sig(m, s.client_key)
            elif s.connection_end == "server":
                # should be TLS 1.3 only
                self.sig._update_sig(m, s.server_key)
        return _TLSHandshake.build(self, *args, **kargs)

    def post_dissection(self, pkt):
        s = self.tls_session
        m = "".join(s.handshake_messages)
        if s.tls_version >= 0x0304:
            if s.connection_end == "client":
                context_string = "TLS 1.3, server CertificateVerify"
            elif s.connection_end == "server":
                context_string = "TLS 1.3, client CertificateVerify"
            m = b"\x20" * 64 + context_string + b"\x00" + s.rcs.hash.digest(m)

        if s.connection_end == "server":
            if s.client_certs and len(s.client_certs) > 0:
                sig_test = self.sig._verify_sig(m, s.client_certs[0])
                if not sig_test:
                    pkt_info = pkt.firstlayer().summary()
                    log_runtime.info(
                        "TLS: invalid CertificateVerify signature [%s]",
                        pkt_info)
        elif s.connection_end == "client":
            # should be TLS 1.3 only
            if s.server_certs and len(s.server_certs) > 0:
                sig_test = self.sig._verify_sig(m, s.server_certs[0])
                if not sig_test:
                    pkt_info = pkt.firstlayer().summary()
                    log_runtime.info(
                        "TLS: invalid CertificateVerify signature [%s]",
                        pkt_info)
Ejemplo n.º 3
0
class TLSServerKeyExchange(_TLSHandshake):
    name = "TLS Handshake - Server Key Exchange"
    fields_desc = [
        ByteEnumField("msgtype", 12, _tls_handshake_type),
        ThreeBytesField("msglen", None),
        _TLSServerParamsField("params",
                              None,
                              length_from=lambda pkt: pkt.msglen),
        _TLSSignatureField(
            "sig", None, length_from=lambda pkt: pkt.msglen - len(pkt.params))
    ]

    def build(self, *args, **kargs):
        """
        We overload build() method in order to provide a valid default value
        for params based on TLS session if not provided. This cannot be done by
        overriding i2m() because the method is called on a copy of the packet.

        The 'params' field is built according to key_exchange.server_kx_msg_cls
        which should have been set after receiving a cipher suite in a
        previous ServerHello. Usual cases are:
        - None: for RSA encryption or fixed FF/ECDH. This should never happen,
          as no ServerKeyExchange should be generated in the first place.
        - ServerDHParams: for ephemeral FFDH. In that case, the parameter to
          server_kx_msg_cls does not matter.
        - ServerECDH*Params: for ephemeral ECDH. There are actually three
          classes, which are dispatched by _tls_server_ecdh_cls_guess on
          the first byte retrieved. The default here is b"\03", which
          corresponds to ServerECDHNamedCurveParams (implicit curves).

        When the Server*DHParams are built via .fill_missing(), the session
        server_kx_privkey will be updated accordingly.
        """
        fval = self.getfieldval("params")
        if fval is None:
            s = self.tls_session
            if s.pwcs:
                if s.pwcs.key_exchange.export:
                    cls = ServerRSAParams(tls_session=s)
                else:
                    cls = s.pwcs.key_exchange.server_kx_msg_cls(b"\x03")
                    cls = cls(tls_session=s)
                try:
                    cls.fill_missing()
                except:
                    pass
            else:
                cls = Raw()
            self.params = cls

        fval = self.getfieldval("sig")
        if fval is None:
            s = self.tls_session
            if s.pwcs:
                if not s.pwcs.key_exchange.anonymous:
                    p = self.params
                    if p is None:
                        p = ""
                    m = s.client_random + s.server_random + str(p)
                    cls = _TLSSignature(tls_session=s)
                    cls._update_sig(m, s.server_key)
                else:
                    cls = Raw()
            else:
                cls = Raw()
            self.sig = cls

        return _TLSHandshake.build(self, *args, **kargs)

    def post_dissection(self, pkt):
        """
        While previously dissecting Server*DHParams, the session
        server_kx_pubkey should have been updated.

        XXX Add a 'fixed_dh' OR condition to the 'anonymous' test.
        """
        s = self.tls_session
        if s.prcs and s.prcs.key_exchange.no_ske:
            print("USELESS SERVER KEY EXCHANGE")
        if (s.prcs and not s.prcs.key_exchange.anonymous and s.client_random
                and s.server_random and s.server_certs
                and len(s.server_certs) > 0):
            m = s.client_random + s.server_random + str(self.params)
            sig_test = self.sig._verify_sig(m, s.server_certs[0])
            if not sig_test:
                print("INVALID SERVER KEY EXCHANGE SIGNATURE")