Esempio n. 1
0
    def genState(self):
        """
        Populate all the local variables with values.
        """

        log.info("Generating parameters for the server's state file.")

        # PRNG seed for the client to reproduce the packet and IAT morpher.
        self.prngSeed = mycrypto.strongRandom(const.PRNG_SEED_LENGTH)

        # HMAC and AES key used to encrypt and authenticate tickets.
        self.hmacKey = mycrypto.strongRandom(const.TICKET_HMAC_KEY_LENGTH)
        self.aesKey = mycrypto.strongRandom(const.TICKET_AES_KEY_LENGTH)
        self.keyCreation = int(time.time())

        # The previous HMAC and AES keys.
        self.oldHmacKey = None
        self.oldAesKey = None

        # Replay dictionary for both authentication mechanisms.
        self.replayTracker = replay.Tracker()

        # Distributions for packet lengths and inter arrival times.
        prng = random.Random(self.prngSeed)
        self.pktDist = probdist.new(
            lambda: prng.randint(const.HDR_LENGTH, const.MTU),
            seed=self.prngSeed)
        self.iatDist = probdist.new(
            lambda: prng.random() % const.MAX_PACKET_DELAY, seed=self.prngSeed)

        # Fallback UniformDH shared secret.  Only used if the bridge operator
        # did not set `ServerTransportOptions'.
        self.fallbackPassword = os.urandom(const.SHARED_SECRET_LENGTH)

        self.writeState()
Esempio n. 2
0
    def genState( self ):
        """
        Populate all the local variables with values.
        """

        log.info("Generating parameters for the server's state file.")

        # PRNG seed for the client to reproduce the packet and IAT morpher.
        self.prngSeed = mycrypto.strongRandom(const.PRNG_SEED_LENGTH)

        # HMAC and AES key used to encrypt and authenticate tickets.
        self.hmacKey = mycrypto.strongRandom(const.TICKET_HMAC_KEY_LENGTH)
        self.aesKey = mycrypto.strongRandom(const.TICKET_AES_KEY_LENGTH)
        self.keyCreation = int(time.time())

        # The previous HMAC and AES keys.
        self.oldHmacKey = None
        self.oldAesKey = None

        # Replay dictionary for both authentication mechanisms.
        self.replayTracker = replay.Tracker()

        # Distributions for packet lengths and inter arrival times.
        prng = random.Random(self.prngSeed)
        self.pktDist = probdist.new(lambda: prng.randint(const.HDR_LENGTH,
                                                         const.MTU),
                                    seed=self.prngSeed)
        self.iatDist = probdist.new(lambda: prng.random() %
                                    const.MAX_PACKET_DELAY,
                                    seed=self.prngSeed)

        self.writeState()
Esempio n. 3
0
    def processMessages( self, circuit, data ):
        """
        Acts on extracted protocol messages based on header flags.

        After the incoming `data' is decrypted and authenticated, this method
        processes the received data based on the header flags.  Payload is
        written to the local application using `circuit', new tickets are
        stored or keys are added to the replay table.
        """

        assert circuit

        if (data is None) or (len(data) == 0):
            return

        # Try to extract protocol messages from the encrypted blurb.
        msgs  = self.extractMessages(data, self.recvCrypter)
        if (msgs is None) or (len(msgs) == 0):
            return

        for msg in msgs:
            # Forward data to the application.
            if msg.flags & const.FLAG_PAYLOAD:
                circuit.upstream.write(msg.payload)

            # Store newly received ticket and send ACK to the server.
            elif self.weAreClient and msg.flags == const.FLAG_NEW_TICKET:
                assert len(msg) == (const.HDR_LENGTH + const.TICKET_LENGTH +
                                    const.MASTER_KEY_LENGTH)
                peer = circuit.downstream.transport.getPeer()
                ticket.storeNewTicket(msg.payload[0:const.MASTER_KEY_LENGTH],
                                      msg.payload[const.MASTER_KEY_LENGTH:
                                                  const.MASTER_KEY_LENGTH +
                                                  const.TICKET_LENGTH], peer)

            # Use the PRNG seed to generate the same probability distributions
            # as the server.  That's where the polymorphism comes from.
            elif self.weAreClient and msg.flags == const.FLAG_PRNG_SEED:
                assert len(msg.payload) == const.PRNG_SEED_LENGTH
                log.debug("Obtained PRNG seed.")
                prng = random.Random(msg.payload)
                pktDist = probdist.new(lambda: prng.randint(const.HDR_LENGTH,
                                                            const.MTU),
                                       seed=msg.payload)
                self.pktMorpher = packetmorpher.new(pktDist)
                self.iatMorpher = probdist.new(lambda: prng.random() %
                                               const.MAX_PACKET_DELAY,
                                               seed=msg.payload)

            else:
                log.warning("Invalid message flags: %d." % msg.flags)
Esempio n. 4
0
    def processMessages(self, data):
        """
        Acts on extracted protocol messages based on header flags.

        After the incoming `data' is decrypted and authenticated, this method
        processes the received data based on the header flags.  Payload is
        written to the local application, new tickets are stored, or keys are
        added to the replay table.
        """

        if (data is None) or (len(data) == 0):
            return

        # Try to extract protocol messages from the encrypted blurb.
        msgs = self.protoMsg.extract(data, self.recvCrypter, self.recvHMAC)
        if (msgs is None) or (len(msgs) == 0):
            return

        for msg in msgs:
            # Forward data to the application.
            if msg.flags == const.FLAG_PAYLOAD:
                self.circuit.upstream.write(msg.payload)

            # Store newly received ticket.
            elif self.weAreClient and (msg.flags == const.FLAG_NEW_TICKET):
                assert len(msg.payload) == (const.TICKET_LENGTH +
                                            const.MASTER_KEY_LENGTH)
                peer = self.circuit.downstream.transport.getPeer()
                ticket.storeNewTicket(
                    msg.payload[0:const.MASTER_KEY_LENGTH], msg.
                    payload[const.MASTER_KEY_LENGTH:const.MASTER_KEY_LENGTH +
                            const.TICKET_LENGTH], peer)

            # Use the PRNG seed to generate the same probability distributions
            # as the server.  That's where the polymorphism comes from.
            elif self.weAreClient and (msg.flags == const.FLAG_PRNG_SEED):
                assert len(msg.payload) == const.PRNG_SEED_LENGTH
                #log.debug("Obtained PRNG seed.")
                prng = random.Random(msg.payload)
                pktDist = probdist.new(
                    lambda: prng.randint(const.HDR_LENGTH, const.MTU),
                    seed=msg.payload)
                self.pktMorpher = packetmorpher.new(pktDist)
                self.iatMorpher = probdist.new(
                    lambda: prng.random() % const.MAX_PACKET_DELAY,
                    seed=msg.payload)

            else:
                #log.warning("Invalid message flags: %d." % msg.flags)
                pass
Esempio n. 5
0
    def __init__( self ):
        """
        Initialise a ScrambleSuitTransport object.
        """

        log.error("\n\n################################################\n"
                  "Do NOT rely on ScrambleSuit for strong security!\n"
                  "################################################\n")

        log.debug("Initialising %s." % const.TRANSPORT_NAME)

        super(ScrambleSuitTransport, self).__init__()

        # Load the server's persistent state from file.
        if self.weAreServer:
            self.srvState = state.load()

        # Initialise the protocol's state machine.
        log.debug("Switching to state ST_WAIT_FOR_AUTH.")
        self.protoState = const.ST_WAIT_FOR_AUTH

        # Buffer for outgoing data.
        self.sendBuf = ""

        # Buffer for inter-arrival time obfuscation.
        self.choppingBuf = fifobuf.Buffer()

        # AES instances to decrypt incoming and encrypt outgoing data.
        self.sendCrypter = mycrypto.PayloadCrypter()
        self.recvCrypter = mycrypto.PayloadCrypter()

        # Packet morpher to modify the protocol's packet length distribution.
        self.pktMorpher = packetmorpher.new(self.srvState.pktDist
                                            if self.weAreServer else None)

        # Inter-arrival time morpher to obfuscate inter arrival times.
        self.iatMorpher = self.srvState.iatDist if self.weAreServer else \
                          probdist.new(lambda: random.random() %
                                       const.MAX_PACKET_DELAY)

        # Used to extract protocol messages from encrypted data.
        self.protoMsg = message.MessageExtractor()

        # Used by the server-side: `True' if the ticket is already
        # decrypted but not yet authenticated.
        self.decryptedTicket = False

        # If we are in external mode we should already have a shared
        # secret set up because of validate_external_mode_cli().
        if self.weAreExternal:
            assert(self.uniformDHSecret)

        if self.weAreClient and not self.weAreExternal:
            # As a client in managed mode, we get the shared secret
            # from callback `handle_socks_args()' per-connection. Set
            # the shared secret to None for now.
            self.uniformDHSecret = None

        self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer)
Esempio n. 6
0
    def test1_calcPadding( self ):

        def checkDistribution( dist ):
            pm = packetmorpher.new(dist)
            for i in xrange(0, const.MTU + 2):
                padLen = pm.calcPadding(i)
                self.assertTrue(const.HDR_LENGTH <= \
                                padLen < \
                                (const.MTU + const.HDR_LENGTH))

        # Test randomly generated distributions.
        for i in xrange(0, 100):
            checkDistribution(None)

        # Test border-case distributions.
        checkDistribution(probdist.new(lambda: 0))
        checkDistribution(probdist.new(lambda: 1))
        checkDistribution(probdist.new(lambda: const.MTU))
        checkDistribution(probdist.new(lambda: const.MTU + 1))
Esempio n. 7
0
File: state.py Progetto: 0xa-cc/pupy
	def genState( self ):
		"""
		Populate all the local variables with values.
		"""

		log.info("Generating parameters for the server's state file.")

		# PRNG seed for the client to reproduce the packet and IAT morpher.
		self.prngSeed = mycrypto.strongRandom(const.PRNG_SEED_LENGTH)

		# HMAC and AES key used to encrypt and authenticate tickets.
		self.hmacKey = mycrypto.strongRandom(const.TICKET_HMAC_KEY_LENGTH)
		self.aesKey = mycrypto.strongRandom(const.TICKET_AES_KEY_LENGTH)
		self.keyCreation = int(time.time())

		# The previous HMAC and AES keys.
		self.oldHmacKey = None
		self.oldAesKey = None

		# Replay dictionary for both authentication mechanisms.
		self.replayTracker = replay.Tracker()

		# Distributions for packet lengths and inter arrival times.
		prng = random.Random(self.prngSeed)
		self.pktDist = probdist.new(lambda: prng.randint(const.HDR_LENGTH,
														 const.MTU),
									seed=self.prngSeed)
		self.iatDist = probdist.new(lambda: prng.random() %
									const.MAX_PACKET_DELAY,
									seed=self.prngSeed)

		# Fallback UniformDH shared secret.  Only used if the bridge operator
		# did not set `ServerTransportOptions'.
		self.fallbackPassword = os.urandom(const.SHARED_SECRET_LENGTH)

		# Unauthenticated connections are closed after having received the
		# following amount of bytes.
		self.closingThreshold = prng.randint(const.MAX_HANDSHAKE_LENGTH,
											 const.MAX_HANDSHAKE_LENGTH * 5)

		self.writeState()
Esempio n. 8
0
    def __init__(self, dist=None):
        """
        Initialise the packet morpher with the given distribution `dist'.

        If `dist' is `None', a new discrete probability distribution is
        generated randomly.
        """

        if dist:
            self.dist = dist
        else:
            self.dist = probdist.new(lambda: random.randint(const.HDR_LENGTH, const.MTU))
Esempio n. 9
0
    def __init__(self, dist=None):
        """
        Initialise the packet morpher with the given distribution `dist'.

        If `dist' is `None', a new discrete probability distribution is
        generated randomly.
        """

        if dist:
            self.dist = dist
        else:
            self.dist = probdist.new(
                lambda: random.randint(const.HDR_LENGTH, const.MTU))
Esempio n. 10
0
    def __init__( self, transportConfig ):
        """
        Initialise a ScrambleSuitTransport object.
        """

        log.error("\n\n################################################\n"
                  "Do NOT rely on ScrambleSuit for strong security!\n"
                  "################################################\n")

        log.debug("Initialising %s." % const.TRANSPORT_NAME)

        util.setStateLocation(transportConfig.getStateLocation())

        # Load the server's persistent state from file.
        if self.weAreServer:
            self.srvState = state.load()

        # Initialise the protocol's state machine.
        log.debug("Switching to state ST_WAIT_FOR_AUTH.")
        self.protoState = const.ST_WAIT_FOR_AUTH

        # Buffers for incoming and outgoing data.
        self.sendBuf = self.recvBuf = ""

        # Buffer for inter-arrival time obfuscation.
        self.choppingBuf = ""

        # AES instances to decrypt incoming and encrypt outgoing data.
        self.sendCrypter = mycrypto.PayloadCrypter()
        self.recvCrypter = mycrypto.PayloadCrypter()

        # Packet morpher to modify the protocol's packet length distribution.
        self.pktMorpher = packetmorpher.new(self.srvState.pktDist
                                            if self.weAreServer else None)

        # Inter-arrival time morpher to obfuscate inter arrival times.
        self.iatMorpher = self.srvState.iatDist if self.weAreServer else \
                          probdist.new(lambda: random.random() %
                                       const.MAX_PACKET_DELAY)

        if self.weAreServer:
            # `True' if the ticket is already decrypted but not yet
            # authenticated.
            self.decryptedTicket = False

            if not hasattr(self, 'uniformDHSecret'):

                # As the server, we get the shared secret from the constructor.
                cfg  = transportConfig.getServerTransportOptions()
                self.uniformDHSecret = base64.b32decode(cfg["password"])
                self.uniformDHSecret = self.uniformDHSecret.strip()

        else:
            # As the client, we get the shared secret from obfsproxy calling
            # `handle_socks_args()'.
            if not hasattr(self, 'uniformDHSecret'):
                self.uniformDHSecret = None

        self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer)

        # Variables used to unpack protocol messages.
        self.totalLen = self.payloadLen = self.flags = None