예제 #1
0
파일: tests.py 프로젝트: guoyu07/pylibsrtp
    def test_rtp_any_ssrc(self):
        # protect RTP
        tx_session = Session(policy=Policy(
            key=KEY,
            ssrc_type=Policy.SSRC_ANY_OUTBOUND))
        protected = tx_session.protect(RTP)
        self.assertEqual(len(protected), 182)

        # bad type
        with self.assertRaises(TypeError) as cm:
            tx_session.protect(4567)
        self.assertEqual(str(cm.exception), 'packet must be bytes')

        # bad length
        with self.assertRaises(ValueError) as cm:
            tx_session.protect(b'0' * 1500)
        self.assertEqual(str(cm.exception), 'packet is too long')

        # unprotect RTP
        rx_session = Session(policy=Policy(
            key=KEY,
            ssrc_type=Policy.SSRC_ANY_INBOUND))
        unprotected = rx_session.unprotect(protected)
        self.assertEqual(len(unprotected), 172)
        self.assertEqual(unprotected, RTP)
예제 #2
0
파일: tests.py 프로젝트: guoyu07/pylibsrtp
    def test_add_remove_stream(self):
        # protect RTP
        tx_session = Session(policy=Policy(
            key=KEY,
            ssrc_type=Policy.SSRC_SPECIFIC,
            ssrc_value=12345))
        protected = tx_session.protect(RTP)
        self.assertEqual(len(protected), 182)

        # add stream and unprotect RTP
        rx_session = Session()
        rx_session.add_stream(Policy(
            key=KEY,
            ssrc_type=Policy.SSRC_SPECIFIC,
            ssrc_value=12345))
        unprotected = rx_session.unprotect(protected)
        self.assertEqual(len(unprotected), 172)
        self.assertEqual(unprotected, RTP)

        # remove stream
        rx_session.remove_stream(12345)

        # try removing stream again
        with self.assertRaises(Error) as cm:
            rx_session.remove_stream(12345)
        self.assertEqual(str(cm.exception), 'no appropriate context found')
예제 #3
0
    def test_rtp_specific_ssrc(self):
        # protect RTP
        tx_session = Session(policy=Policy(
            key=KEY, ssrc_type=Policy.SSRC_SPECIFIC, ssrc_value=12345))
        protected = tx_session.protect(RTP)
        self.assertEqual(len(protected), 182)

        # unprotect RTP
        rx_session = Session(policy=Policy(
            key=KEY, ssrc_type=Policy.SSRC_SPECIFIC, ssrc_value=12345))
        unprotected = rx_session.unprotect(protected)
        self.assertEqual(len(unprotected), 172)
        self.assertEqual(unprotected, RTP)
예제 #4
0
파일: tests.py 프로젝트: guoyu07/pylibsrtp
    def test_key(self):
        policy = Policy()
        self.assertEqual(policy.key, None)

        policy.key = KEY
        self.assertEqual(policy.key, KEY)

        policy.key = None
        self.assertEqual(policy.key, None)

        with self.assertRaises(TypeError) as cm:
            policy.key = 1234
        self.assertEqual(policy.key, None)
        self.assertEqual(str(cm.exception), 'key must be bytes')
예제 #5
0
    async def connect(self):
        assert self.state == self.State.CLOSED

        self._set_state(self.State.CONNECTING)
        while not self.encrypted:
            result = lib.SSL_do_handshake(self.ssl)
            await self._write_ssl()

            if result > 0:
                self.encrypted = True
                break

            error = lib.SSL_get_error(self.ssl, result)
            if error == lib.SSL_ERROR_WANT_READ:
                await self._recv_next()
            else:
                raise DtlsError('DTLS handshake failed (error %d)' % error)

        # check remote fingerprint
        x509 = lib.SSL_get_peer_certificate(self.ssl)
        remote_fingerprint = certificate_digest(x509)
        if remote_fingerprint != self.remote_fingerprint.upper():
            raise DtlsError('DTLS fingerprint does not match')

        # generate keying material
        buf = ffi.new('unsigned char[]', 2 * (SRTP_KEY_LEN + SRTP_SALT_LEN))
        extractor = b'EXTRACTOR-dtls_srtp'
        _openssl_assert(
            lib.SSL_export_keying_material(self.ssl, buf, len(
                buf), extractor, len(extractor), ffi.NULL, 0, 0) == 1)

        view = ffi.buffer(buf)
        if self.is_server:
            srtp_tx_key = get_srtp_key_salt(view, 1)
            srtp_rx_key = get_srtp_key_salt(view, 0)
        else:
            srtp_tx_key = get_srtp_key_salt(view, 0)
            srtp_rx_key = get_srtp_key_salt(view, 1)

        rx_policy = Policy(key=srtp_rx_key, ssrc_type=Policy.SSRC_ANY_INBOUND)
        self._rx_srtp = Session(rx_policy)
        tx_policy = Policy(key=srtp_tx_key, ssrc_type=Policy.SSRC_ANY_OUTBOUND)
        self._tx_srtp = Session(tx_policy)

        # start data pump
        logger.debug('%s - DTLS handshake complete', self.role)
        self._set_state(self.State.CONNECTED)
        asyncio.ensure_future(self.__run())
예제 #6
0
    async def connect(self):
        while not self.encrypted:
            result = lib.SSL_do_handshake(self.ssl)
            if result > 0:
                self.encrypted = True
                break

            error = lib.SSL_get_error(self.ssl, result)

            await self._write_ssl()

            if error == lib.SSL_ERROR_WANT_READ:
                data = await self.transport.recv()
                lib.BIO_write(self.read_bio, data, len(data))
            else:
                raise Exception('DTLS handshake failed (error %d)' % error)

        await self._write_ssl()

        # check remote fingerprint
        x509 = lib.SSL_get_peer_certificate(self.ssl)
        remote_fingerprint = certificate_digest(x509)
        if remote_fingerprint != self.remote_fingerprint.upper():
            raise Exception('DTLS fingerprint does not match')

        # generate keying material
        buf = ffi.new("char[]", 2 * (SRTP_KEY_LEN + SRTP_SALT_LEN))
        extractor = b'EXTRACTOR-dtls_srtp'
        if not lib.SSL_export_keying_material(self.ssl, buf,
                                              len(buf), extractor,
                                              len(extractor), ffi.NULL, 0, 0):
            raise Exception('DTLS could not extract SRTP keying material')

        view = ffi.buffer(buf)
        if self.is_server:
            srtp_tx_key = get_srtp_key_salt(view, 1)
            srtp_rx_key = get_srtp_key_salt(view, 0)
        else:
            srtp_tx_key = get_srtp_key_salt(view, 0)
            srtp_rx_key = get_srtp_key_salt(view, 1)

        logger.info('DTLS handshake complete')
        rx_policy = Policy(key=srtp_rx_key, ssrc_type=Policy.SSRC_ANY_INBOUND)
        self._rx_srtp = Session(rx_policy)
        tx_policy = Policy(key=srtp_tx_key, ssrc_type=Policy.SSRC_ANY_OUTBOUND)
        self._tx_srtp = Session(tx_policy)
예제 #7
0
    def test_rtcp_any_ssrc(self):
        # protect RCTP
        tx_session = Session(
            policy=Policy(key=KEY, ssrc_type=Policy.SSRC_ANY_OUTBOUND))
        protected = tx_session.protect_rtcp(RTCP)
        self.assertEqual(len(protected), 42)

        # bad type
        with self.assertRaises(TypeError) as cm:
            tx_session.protect_rtcp(4567)
        self.assertEqual(str(cm.exception), "packet must be bytes")

        # bad length
        with self.assertRaises(ValueError) as cm:
            tx_session.protect_rtcp(b"0" * 1500)
        self.assertEqual(str(cm.exception), "packet is too long")

        # unprotect RTCP
        rx_session = Session(
            policy=Policy(key=KEY, ssrc_type=Policy.SSRC_ANY_INBOUND))
        unprotected = rx_session.unprotect_rtcp(protected)
        self.assertEqual(len(unprotected), 28)
        self.assertEqual(unprotected, RTCP)
예제 #8
0
    def test_allow_repeat_tx(self):
        policy = Policy()
        self.assertEqual(policy.allow_repeat_tx, False)

        policy.allow_repeat_tx = True
        self.assertEqual(policy.allow_repeat_tx, True)

        policy.allow_repeat_tx = False
        self.assertEqual(policy.allow_repeat_tx, False)

        policy.allow_repeat_tx = 1
        self.assertEqual(policy.allow_repeat_tx, True)

        policy.allow_repeat_tx = 0
        self.assertEqual(policy.allow_repeat_tx, False)
예제 #9
0
    def record_rtp_packet(self, packet, is_last=False):
        if not packet:
            print("No packet")
            return False

        if self.verbose:
            print("Dumping packet ", packet)

        rtp_raw_full = None
        try:
            rtp_raw_full = bytes.fromhex(''.join(packet[self.rtp_offset:]))
        except:
            print("Failed to get hex", packet)
            return False

        if len(rtp_raw_full) < RTP_FIXED_HEADER:
            print("udp payload is too small")
            return False

        if self.verbose:
            print(self.rtp_offset, packet[self.rtp_offset - 1],
                  packet[self.rtp_offset], packet[self.rtp_offset + 1])

        # decode RTP Header
        rtp_raw_header = rtp_raw_full[:RTP_FIXED_HEADER]

        if self.verbose:
            print(rtp_raw_header.hex())
        rtp = RTP_HEADER._make(struct.unpack(RTP_HEADER_FMT, rtp_raw_header))
        if self.verbose:
            print(rtp)
        if rtp.PAYLOAD_TYPE & 0b10000000:
            # strip marker bit from payload
            rtp = RTP_HEADER(FIRST=rtp.FIRST,
                             PAYLOAD_TYPE=rtp.PAYLOAD_TYPE & 0b01111111,
                             SEQUENCE_NUMBER=rtp.SEQUENCE_NUMBER,
                             TIMESTAMP=rtp.TIMESTAMP,
                             SSRC=rtp.SSRC)
            print('stripped marker bit', rtp)

        # Filter the RTP with v=2
        if (rtp.FIRST & 0b11000000) != 0b10000000:
            print("Not an RTP")
            return False

        rtp_exten = rtp.FIRST & 0b10000
        rtp_exten_length = 0
        rtp_csrc = rtp.FIRST & 0b1111

        # calculate rtp header length
        calc_rtp_header_len = RTP_FIXED_HEADER + rtp_csrc * 4
        if rtp_exten:
            exten_start = RTP_FIXED_HEADER + rtp_csrc * 4
            exten_raw = rtp_raw_full[exten_start:exten_start + 4]
            if len(exten_raw) != 4:
                print("Skipping malformed RTP")
                return False
            rtp_exten_profile, rtp_exten_length = struct.unpack(
                '>HH', exten_raw)
            calc_rtp_header_len += 4 + rtp_exten_length * 4

        if self.verbose:
            print("calc_rtp_header_len", calc_rtp_header_len)

        if self.override_payload_offset:
            calc_rtp_header_len = self.override_payload_offset - self.rtp_offset

        # Filter opus
        if self.payload_type and rtp.PAYLOAD_TYPE != self.payload_type:
            print(
                "Skipping payload {rtp_payload_type} while {opus_payload_type} expected."
                .format(rtp_payload_type=rtp.PAYLOAD_TYPE,
                        opus_payload_type=self.payload_type))
            return False

        if self.filter_ssrc and self.filter_ssrc != rtp.SSRC:
            print(
                "Skipping ssrc={rtp_ssrc} while {filter_ssrc} expected".format(
                    rtp_ssrc=rtp.SSRC, filter_ssrc=self.filter_ssrc))
            return False

        if len(rtp_raw_full) < (calc_rtp_header_len + 1):
            print("Empty payload")
            return False

        if self.srtpkey:
            if self.ssrc != rtp.SSRC:
                #if not self.srtp_session:
                #    self.srtp_session = Session()
                self.srtp_session = Session()
                print("using key [%s]" % self.srtpkey)
                srtpkey = base64.b64decode(self.srtpkey)
                plc = Policy(key=srtpkey,
                             ssrc_value=rtp.SSRC,
                             ssrc_type=Policy.SSRC_ANY_INBOUND)
                print(plc)
                self.srtp_session.add_stream(plc)
                self.ssrc = rtp.SSRC
            try:
                rtp_raw_full = self.srtp_session.unprotect(rtp_raw_full)
            except:
                print("decrypt fail seq={sequence}, ssrc={ssrc}".format(
                    sequence=rtp.SEQUENCE_NUMBER, ssrc=rtp.SSRC))
                '''
                if self.resrtpkey:
                    srtpkey = base64.b64decode(self.resrtpkey)
                    plc = Policy(key=srtpkey,ssrc_value=rtp.SSRC,ssrc_type=Policy.SSRC_ANY_INBOUND)
                    self.srtp_session.add_stream(plc)
                    print("Using restrpkey here from next packet")
                '''
                return False

        self.write_udp(
            bytes.fromhex(''.join(packet[:self.rtp_offset])) + rtp_raw_full)
        return True
예제 #10
0
    def playback_as_srtp_stream(self, infile, outfile, starting_sequence=0):
        '''
        Read an ogg file and create rtp/srtp in hex form
        '''
        self.ogg.reset(open(infile, 'rb'))

        with open(outfile, 'w') as hex_fd:
            page_counter = 0
            sequence_counter = starting_sequence
            for header, content in self.ogg:
                print(header)
                if 0 == page_counter:
                    opus_identity_head = OPUS_IDENTITY_HEADER._make(
                        struct.unpack(OPUS_IDENTITY_HEADER_FMT, content))
                    print(opus_identity_head)
                #elif 1 == page_counter:
                #    opus_comment_head = OPUS_COMMENT_HEADER._make(struct.unpack(OPUS_COMMENT_HEADER_FMT, content))
                #    print(opus_comment_head)
                else:
                    print(' '.join([hex(x) for x in content]))
                    if page_counter > 1:
                        # show the TOC byte
                        #toc = content[0]
                        #config = (toc >> 3)
                        #s = toc & 0b100
                        #s = s >> 2
                        #num_frames = toc & 0b11
                        #print("config %d, s %d, c/frames %d" % (config, s, num_frames))

                        # make an RTP packet
                        rtp = RTP_HEADER(0x80, self.payload_type,
                                         sequence_counter, header.GRANULE_POS,
                                         header.BITSTREAM)
                        rtp_raw_full = struct.pack(RTP_HEADER_FMT, *
                                                   rtp) + content

                        if self.srtpkey:
                            if self.ssrc != rtp.SSRC:
                                print("using key [%s]" % self.srtpkey)
                                srtpkey = base64.b64decode(self.srtpkey)
                                plc = Policy(
                                    key=srtpkey,
                                    ssrc_value=rtp.SSRC,
                                    ssrc_type=Policy.SSRC_ANY_OUTBOUND)
                                print(plc)
                                self.srtp_session = Session(policy=plc)
                                self.ssrc = rtp.SSRC
                            try:
                                rtp_raw_full = self.srtp_session.protect(
                                    rtp_raw_full)
                            except:
                                print(
                                    "encrypt fail seq={sequence}, ssrc={ssrc}".
                                    format(sequence=rtp.SEQUENCE_NUMBER,
                                           ssrc=rtp.SSRC))

                        hex_fd.write(self.hexdump(rtp_raw_full))
                        if sequence_counter == MAX_RTP_SEQUENCE_NUM:
                            sequence_counter = 0
                        else:
                            sequence_counter += 1

                page_counter += 1
                print("Read %d pages" % page_counter)
예제 #11
0
    def record_rtp_packet(self, packet, is_last=False):
        assert self.ogg is not None

        if not packet:
            print("No packet")
            return False

        if self.verbose:
            print("Dumping packet ", packet)

        rtp_raw_full = None
        try:
            rtp_raw_full = bytes.fromhex(''.join(packet[self.rtp_offset:]))
        except:
            print("Failed to get hex", packet)
            return False

        if len(rtp_raw_full) < RTP_FIXED_HEADER:
            print("udp payload is too small")
            return False

        if self.verbose:
            print(self.rtp_offset, packet[self.rtp_offset - 1],
                  packet[self.rtp_offset], packet[self.rtp_offset + 1])

        # decode RTP Header
        rtp_raw_header = rtp_raw_full[:RTP_FIXED_HEADER]

        if self.verbose:
            print(rtp_raw_header.hex())
        rtp = RTP_HEADER._make(struct.unpack(RTP_HEADER_FMT, rtp_raw_header))
        if self.verbose:
            print(rtp)

        # Filter the RTP with v=2
        if (rtp.FIRST & 0b11000000) != 0b10000000:
            print("Not an RTP")
            return False

        rtp_exten = rtp.FIRST & 0b10000
        rtp_exten_length = 0
        rtp_csrc = rtp.FIRST & 0b1111

        # calculate rtp header length
        calc_rtp_header_len = RTP_FIXED_HEADER + rtp_csrc * 4
        if rtp_exten:
            exten_start = RTP_FIXED_HEADER + rtp_csrc * 4
            exten_raw = rtp_raw_full[exten_start:exten_start + 4]
            if len(exten_raw) != 4:
                print("Skipping malformed RTP")
                return False
            rtp_exten_profile, rtp_exten_length = struct.unpack(
                '>HH', exten_raw)
            calc_rtp_header_len += 4 + rtp_exten_length * 4

        if self.verbose:
            print("calc_rtp_header_len", calc_rtp_header_len)

        if self.override_payload_offset:
            calc_rtp_header_len = self.override_payload_offset - self.rtp_offset

        # Filter opus
        if self.payload_type and rtp.PAYLOAD_TYPE != self.payload_type:
            print(
                "Skipping payload {rtp_payload_type} while {opus_payload_type} expected."
                .format(rtp_payload_type=rtp.PAYLOAD_TYPE,
                        opus_payload_type=self.payload_type))
            return False

        if self.filter_ssrc and self.filter_ssrc != rtp.SSRC:
            print(
                "Skipping ssrc={rtp_ssrc} while {filter_ssrc} expected".format(
                    rtp_ssrc=rtp.SSRC, filter_ssrc=self.filter_ssrc))
            return False

        if len(rtp_raw_full) < (calc_rtp_header_len + 1):
            print("Empty payload")
            return False

        if self.srtpkey:
            if self.ssrc != rtp.SSRC:
                if not self.srtp_session:
                    self.srtp_session = Session()
                print("using key [%s]" % self.srtpkey)
                srtpkey = base64.b64decode(self.srtpkey)
                plc = Policy(key=srtpkey,
                             ssrc_value=rtp.SSRC,
                             ssrc_type=Policy.SSRC_ANY_INBOUND)
                print(plc)
                self.srtp_session.add_stream(plc)
                self.ssrc = rtp.SSRC
            try:
                rtp_raw_full = self.srtp_session.unprotect(rtp_raw_full)
            except:
                print("decrypt fail seq={sequence}, ssrc={ssrc}".format(
                    sequence=rtp.SEQUENCE_NUMBER, ssrc=rtp.SSRC))
                '''
                if self.resrtpkey:
                    srtpkey = base64.b64decode(self.resrtpkey)
                    plc = Policy(key=srtpkey,ssrc_value=rtp.SSRC,ssrc_type=Policy.SSRC_ANY_INBOUND)
                    self.srtp_session.add_stream(plc)
                    print("Using restrpkey here from next packet")
                '''
                return False

        # Add bitstream header
        if self.ogg.get_curr_bitstream() != rtp.SSRC:
            self.write_stream_header(rtp.SSRC)
            self.write_stream_comment('hex_to_opus', [str(rtp)])

        # rtp_payload = rtp_raw_full[RTP_FIXED_HEADER:]
        rtp_payload = rtp_raw_full[calc_rtp_header_len:]
        self.ogg.write_page(
            rtp_payload,
            is_data=True,
            is_last=is_last,
            ptime=20,
            pageno=rtp.SEQUENCE_NUMBER)  # By default the ptime=20
        return True
예제 #12
0
파일: tests.py 프로젝트: guoyu07/pylibsrtp
    def test_no_key(self):
        policy = Policy(ssrc_type=Policy.SSRC_ANY_OUTBOUND)

        with self.assertRaises(Error) as cm:
            Session(policy=policy)
        self.assertEqual(str(cm.exception), 'unsupported parameter')
예제 #13
0
파일: tests.py 프로젝트: guoyu07/pylibsrtp
    def test_ssrc_type(self):
        policy = Policy()
        self.assertEqual(policy.ssrc_type, Policy.SSRC_UNDEFINED)

        policy.ssrc_type = Policy.SSRC_ANY_INBOUND
        self.assertEqual(policy.ssrc_type, Policy.SSRC_ANY_INBOUND)
예제 #14
0
    def test_window_size(self):
        policy = Policy()
        self.assertEqual(policy.window_size, 0)

        policy.window_size = 1024
        self.assertEqual(policy.window_size, 1024)
예제 #15
0
    async def start(self, remoteParameters: RTCDtlsParameters) -> None:
        """
        Start DTLS transport negotiation with the parameters of the remote
        DTLS transport.

        :param remoteParameters: An :class:`RTCDtlsParameters`.
        """
        assert self._state == State.NEW
        assert len(remoteParameters.fingerprints)

        if self.transport.role == "controlling":
            self._role = "server"
            lib.SSL_set_accept_state(self.ssl)
        else:
            self._role = "client"
            lib.SSL_set_connect_state(self.ssl)

        self._set_state(State.CONNECTING)
        try:
            while not self.encrypted:
                result = lib.SSL_do_handshake(self.ssl)
                await self._write_ssl()

                if result > 0:
                    self.encrypted = True
                    break

                error = lib.SSL_get_error(self.ssl, result)
                if error == lib.SSL_ERROR_WANT_READ:
                    await self._recv_next()
                else:
                    self.__log_debug("x DTLS handshake failed (error %d)",
                                     error)
                    for info in get_error_queue():
                        self.__log_debug("x %s", ":".join(info))
                    self._set_state(State.FAILED)
                    return
        except ConnectionError:
            self.__log_debug("x DTLS handshake failed (connection error)")
            self._set_state(State.FAILED)
            return

        # check remote fingerprint
        x509 = lib.SSL_get_peer_certificate(self.ssl)
        remote_fingerprint = certificate_digest(x509)
        fingerprint_is_valid = False
        for f in remoteParameters.fingerprints:
            if (f.algorithm.lower() == "sha-256"
                    and f.value.lower() == remote_fingerprint.lower()):
                fingerprint_is_valid = True
                break
        if not fingerprint_is_valid:
            self.__log_debug("x DTLS handshake failed (fingerprint mismatch)")
            self._set_state(State.FAILED)
            return

        # generate keying material
        buf = ffi.new("unsigned char[]", 2 * (SRTP_KEY_LEN + SRTP_SALT_LEN))
        extractor = b"EXTRACTOR-dtls_srtp"
        _openssl_assert(
            lib.SSL_export_keying_material(self.ssl, buf, len(
                buf), extractor, len(extractor), ffi.NULL, 0, 0) == 1)

        view = ffi.buffer(buf)
        if self._role == "server":
            srtp_tx_key = get_srtp_key_salt(view, 1)
            srtp_rx_key = get_srtp_key_salt(view, 0)
        else:
            srtp_tx_key = get_srtp_key_salt(view, 0)
            srtp_rx_key = get_srtp_key_salt(view, 1)

        rx_policy = Policy(key=srtp_rx_key, ssrc_type=Policy.SSRC_ANY_INBOUND)
        rx_policy.allow_repeat_tx = True
        rx_policy.window_size = 1024
        self._rx_srtp = Session(rx_policy)

        tx_policy = Policy(key=srtp_tx_key, ssrc_type=Policy.SSRC_ANY_OUTBOUND)
        tx_policy.allow_repeat_tx = True
        tx_policy.window_size = 1024
        self._tx_srtp = Session(tx_policy)

        # start data pump
        self.__log_debug("- DTLS handshake complete")
        self._set_state(State.CONNECTED)
        self._task = asyncio.ensure_future(self.__run())
예제 #16
0
    async def start(self, remoteParameters):
        """
        Start DTLS transport negotiation with the parameters of the remote
        DTLS transport.

        :param: remoteParameters: An :class:`RTCDtlsParameters`.
        """
        assert self._state not in [State.CLOSED, State.FAILED]
        assert len(remoteParameters.fingerprints)

        # handle the case where start is already in progress
        if self._start is not None:
            return await self._start.wait()
        self._start = asyncio.Event()

        if self.transport.role == 'controlling':
            self._role = 'server'
            lib.SSL_set_accept_state(self.ssl)
        else:
            self._role = 'client'
            lib.SSL_set_connect_state(self.ssl)

        self._set_state(State.CONNECTING)
        while not self.encrypted:
            result = lib.SSL_do_handshake(self.ssl)
            await self._write_ssl()

            if result > 0:
                self.encrypted = True
                break

            error = lib.SSL_get_error(self.ssl, result)
            if error == lib.SSL_ERROR_WANT_READ:
                await self._recv_next()
            else:
                self._set_state(State.FAILED)
                raise DtlsError('DTLS handshake failed (error %d)' % error)

        # check remote fingerprint
        x509 = lib.SSL_get_peer_certificate(self.ssl)
        remote_fingerprint = certificate_digest(x509)
        fingerprint_is_valid = False
        for f in remoteParameters.fingerprints:
            if f.algorithm == 'sha-256' and f.value.lower(
            ) == remote_fingerprint.lower():
                fingerprint_is_valid = True
                break
        if not fingerprint_is_valid:
            self._set_state(State.FAILED)
            raise DtlsError('DTLS fingerprint does not match')

        # generate keying material
        buf = ffi.new('unsigned char[]', 2 * (SRTP_KEY_LEN + SRTP_SALT_LEN))
        extractor = b'EXTRACTOR-dtls_srtp'
        _openssl_assert(
            lib.SSL_export_keying_material(self.ssl, buf, len(
                buf), extractor, len(extractor), ffi.NULL, 0, 0) == 1)

        view = ffi.buffer(buf)
        if self._role == 'server':
            srtp_tx_key = get_srtp_key_salt(view, 1)
            srtp_rx_key = get_srtp_key_salt(view, 0)
        else:
            srtp_tx_key = get_srtp_key_salt(view, 0)
            srtp_rx_key = get_srtp_key_salt(view, 1)

        rx_policy = Policy(key=srtp_rx_key, ssrc_type=Policy.SSRC_ANY_INBOUND)
        rx_policy.allow_repeat_tx = True
        rx_policy.window_size = 1024
        self._rx_srtp = Session(rx_policy)

        tx_policy = Policy(key=srtp_tx_key, ssrc_type=Policy.SSRC_ANY_OUTBOUND)
        tx_policy.allow_repeat_tx = True
        tx_policy.window_size = 1024
        self._tx_srtp = Session(tx_policy)

        # start data pump
        self.__log_debug('- DTLS handshake complete')
        self._set_state(State.CONNECTED)
        asyncio.ensure_future(self.__run())
        self._start.set()
예제 #17
0
파일: tests.py 프로젝트: guoyu07/pylibsrtp
    def test_ssrc_value(self):
        policy = Policy()
        self.assertEqual(policy.ssrc_value, 0)

        policy.ssrc_value = 12345
        self.assertEqual(policy.ssrc_value, 12345)