Esempio n. 1
0
    def get_entropy_input(self, security_strength,
                          min_bits, max_bits,
                          prediction_resistance):
        min_bytes = (min_bits + 7) / 8
        try:
            ctr = 0
            random_bytes = ''
            while len(random_bytes) < min_bytes and ctr < 10:
                random_bytes += (
                    self.qrng.wesQrngEntropyGet(min_bytes - len(random_bytes)))
                ctr += 1

            logging.debug("Got %s bytes from qrng.", len(random_bytes))

            random_bytes = utilities.binstr_leftmost(random_bytes, max_bits)

            if len(random_bytes) >= min_bytes:
                self.total_bytes += len(random_bytes)
                return 'SUCCESS', random_bytes
            else:
                return 'ERROR', ("Unable to get the requested entropy. " +
                                 "Only got %s bytes." % len(random_bytes))
        except eWesQrngError as error:
            logging.error(error.msg)
            raise
Esempio n. 2
0
    def hash_df(self, input_string, n_bits):
        '''
        Hash_df as specified in NIST SP800-90A, Section 10.4.1, page 67
        '''

        if n_bits > 255 * self.outlen:
            return 'ERROR', ''

        # Step 1
        temp = ''

        # Step 2
        len_blocks = (n_bits + self.outlen - 1) / self.outlen

        # Step 3
        counter = 1

        # Step 4
        for dummy_ii in range(len_blocks):
            # Step 4.1
            temp = temp + self.hash(struct.pack('>II', counter, n_bits) +
                                    input_string)
            # Step 4.2
            counter += 1

        # Step 5
        requested_bits = utilities.binstr_leftmost(temp, n_bits)

        # Step 6
        return 'SUCCESS', requested_bits
Esempio n. 3
0
    def hashgen(self, n_bits, V):
        '''
        Hashgen, as specified in NIST SP800-90A, Section 10.1.1.4, page 43
        '''

        # Step 1
        mm = (n_bits + self.outlen - 1) / self.outlen

        # Step 2
        data = V

        # Step 3
        W = ''

        # Step 4
        for dummy_ii in range(mm):
            # Step 4.1
            wi = self.hash(data)
            # Step 4.2
            W = W + wi
            # Step 4.3
            data = utilities.binstr_increment(data, self.seedlen)

        # Step 5
        returned_bits = utilities.binstr_leftmost(W, n_bits)

        # Step 6
        return returned_bits
Esempio n. 4
0
    def generate_algorithm(self, n_bits, additional_input = None):
        '''
        CTR_DRGB_Generate_algorithm, as specified in NIST SP800-90A,
        Section 10.2.1.5, page 56.
        Generate bits either with (10.2.1.5.2) or without (10.2.1.5.2)
        a derivation function.
        '''

        # Step 1
        if self.counter > self.max_interval and not self.reseed_failed:
            return ('RESEED', '')

        # Step 2
        if additional_input:
            if self.derivation:
                # 10.2.1.5.2, Step 2.1
                status, additional_input = self.block_cipher_df(
                    additional_input, self.seedlen)
                if status != 'SUCCESS':
                    return 'ERROR', 'block_cipher_df returned [%s]' % status
            else:
                # 10.2.1.5.1, Step 2.1-2.2
                additional_input = utilities.binstr_zeropad(
                    additional_input, self.seedlen)
            # 10.2.1.5.1, Step 2.3 / 10.2.1.5.2, Step 2.2
            self.update(additional_input)
        else:
            additional_input = utilities.binstr_zeropad('', self.seedlen)

        # Step 3
        temp = ''

        # Step 4
        while len(temp) < (n_bits + 7) / 8:
            # Step 4.1
            self.V = utilities.binstr_increment(self.V, self.outlen)
            # Step 4.2
            output_block = self.block_encrypt(self.key, self.V)
            # Step 4.3
            temp = temp + output_block

        # Step 5
        returned_bits = utilities.binstr_leftmost(temp, n_bits)

        # Step 6
        self.update(additional_input)

        # Step 7
        self.counter += 1

        # Step 8
        if not self.reseed_failed:
            return ('SUCCESS', returned_bits)
        else:
            return ('RESEED', returned_bits)
    def get_entropy_input(self, security_strength,
                          min_bits, max_bits,
                          prediction_resistance):
        '''Return entropy from network source.'''

        if max_bits < min_bits:
            raise ValueError('max_length must be greater than or ' +
                             'equal to min_length')

        min_bytes = (min_bits + 7) / 8

        random_bytes = ''
        backoff = 0.01

        if not self.init_event.is_set():
            while not self.init_event.is_set():
                time.sleep(.1)

            # TODO: Make less hacky (still timing based)
            time.sleep(1)

        # Only try to get data when buffer isn't empty to prevent
        #  a two second decay when qrng goes down and drbg is running
        #  off old seed (qrng as seed case).
        if self.buff.bytes_ready() > 0:
            while len(random_bytes) < min_bytes:
                with self.lock:
                    new_bytes = self.buff.get_random_data(
                        min_bytes)

                if len(new_bytes) == 0:
                    logging.debug("Sleep %f", backoff)
                    if backoff > 2.0:
                        break
                    time.sleep(backoff)
                    backoff = backoff * 2
                else:
                    backoff = 0.01
                    random_bytes += str(new_bytes)

            self.total_bytes += len(random_bytes)

            random_bytes = utilities.binstr_leftmost(random_bytes, max_bits)

        if len(random_bytes) >= min_bytes:
            return 'SUCCESS', random_bytes
        else:
            self.restart_fifo_client()
            return 'ERROR', (("Internal pool doesn't contain "
                              "enough entropy. Only got %i bytes.") %
                             len(random_bytes))
    def get_entropy_input(self, security_strength,
                          min_bits, max_bits,
                          prediction_resistance):
        '''Return entropy from network source.'''

        # If initializing, wait up to 30 seconds to allow network to connect.
        if self.state < 2:
            timeout_start = time.time()
            timeout = 30

            while self.state < 2 and time.time() < timeout_start + timeout:
                time.sleep(.1)

        if max_bits < min_bits:
            raise ValueError('max_length must be greater than or ' +
                             'equal to min_length')

        min_bytes = (min_bits + 7) / 8

        # To encrypt with AES, must have blocks of 16 bytes
        aes_bytes = ((min_bytes + 15) / 16) * 16

        random_bytes = ''
        backoff = 0.01

        # Only try to get data when buffer isn't empty to prevent
        #  a two second decay when network goes down and drbg is running
        #  off old seed (network as seed case).
        if self.buff.bytes_ready() > 0:
            while len(random_bytes) < aes_bytes:
                with self.lock:
                    new_bytes = self.buff.get_random_data(aes_bytes -
                                                          len(random_bytes))

                if len(new_bytes) == 0:
                    logging.warning("Sleep %f", backoff)
                    if backoff > 2.0:
                        break
                    time.sleep(backoff)
                    backoff = backoff * 2
                else:
                    backoff = 0.01
                    random_bytes += str(new_bytes)

            # If we haven't hit a timeout
            if len(random_bytes) == aes_bytes:
                random_bytes = self.aes_key.encrypt(random_bytes)

                if len(random_bytes) > min_bytes:
                    random_bytes = random_bytes[0:min_bytes]

                self.total_bytes += len(random_bytes)

                if (self.total_bytes >
                        self.last_rekey + NetworkEntropySource.REKEY_PERIOD):
                    self.rekey()

                random_bytes = utilities.binstr_leftmost(random_bytes, max_bits)

                if len(random_bytes) >= min_bytes:
                    return 'SUCCESS', random_bytes

        return 'ERROR', (("Internal pool doesn't contain "
                          "enough entropy. Only got %i bytes.") %
                         len(random_bytes))