From 3ddce8a1008a4ae08e8f0bcdd4c22ccb1937814c Mon Sep 17 00:00:00 2001 From: Joris van Rantwijk Date: Fri, 18 Nov 2016 15:34:27 +0100 Subject: [PATCH] Add Trivium RNG (to be tested). --- rtl/rng_trivium.vhdl | 182 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 rtl/rng_trivium.vhdl diff --git a/rtl/rng_trivium.vhdl b/rtl/rng_trivium.vhdl new file mode 100644 index 0000000..214c7e3 --- /dev/null +++ b/rtl/rng_trivium.vhdl @@ -0,0 +1,182 @@ +-- +-- Pseudo Random Number Generator "Trivium". +-- +-- Author: Joris van Rantwijk +-- +-- This is a pseudo-random number generator in synthesizable VHDL. +-- The generator produces up to 64 new random bits on every clock cycle. +-- +-- The algorithm "Trivium" is by Christophe De Canniere and Bart Preneel. +-- See also: +-- C. De Canniere, B. Preneel, "Trivium Specifications", (TODO URL). +-- +-- The generator requires an 80-bit key and an 80-bit initialization +-- vector. Defaults for these values must be supplied at compile time +-- and will be used to initialize the generator at reset. The generator +-- also supports re-keying at run time. +-- +-- After reset and after re-seeding, at least 4*288 clock cycles are needed +-- before valid random data appears on the output. +-- +-- NOTE: This generator is designed to produce up to 2**64 bits +-- of secure random data. If more than 2**64 bits are generated +-- with the same key and IV, it becomes inceasingly likely that +-- the output contains patterns and correlations. +-- + +-- +-- Copyright (C) 2016 Joris van Rantwijk +-- +-- This code is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public +-- License as published by the Free Software Foundation; either +-- version 2.1 of the License, or (at your option) any later version. +-- +-- See +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity rng_trivium is + + generic ( + -- Number of output bits per clock cycle. + num_bits: integer range 1 to 64; + + -- Default key. + init_key: std_logic_vector(79 downto 0); + + -- Default initialization vector. + init_iv: std_logic_vector(79 downto 0) ); + + port ( + + -- Clock, rising edge active. + clk: in std_logic; + + -- Synchronous reset, active high. + rst: in std_logic; + + -- High to request re-seeding of the generator. + reseed: in std_logic; + + -- New key value (must be valid when reseed = '1'). + in_key: in std_logic_vector(79 downto 0); + + -- New initialization vector (must be valid when reseed = '1'). + in_iv: in std_logic_vector(79 downto 0); + + -- High when the user accepts the current random data word + -- and requests new random data for the next clock cycle. + out_ready: in std_logic; + + -- High when valid random data is available on the output. + -- This signal is low during the first 4*288 clock cycle after reset + -- and after re-seeding, and high in all other cases. + out_valid: out std_logic; + + -- Random output data (valid when out_valid = '1'). + -- A new random word appears after every rising clock edge + -- where out_ready = '1'. + out_data: out std_logic_vector(num_bits-1 downto 0) ); + +end entity; + + +architecture trivium_arch of rng_trivium is + + -- Fixed bit strings to fill up initial state after reseeding. + constant zeros13: std_logic_vector(12 downto 0) := (others => '0'); + constant zeros4: std_logic_vector(3 downto 0) := (others => '0'); + constant zeros108: std_logic_vector(107 downto 0) := (others => '0'); + constant ones3: std_logic_vector(2 downto 0) := (others => '1'); + + -- Internal state of RNG. + signal reg_state: std_logic_vector(287 downto 0) := + ones3 & zeros108 & zeros4 & init_iv & zeros13 & init_key; + + signal reg_valid_wait: unsigned(10 downto 0) := (others => '0'); + + -- Output register. + signal reg_valid: std_logic := '0'; + signal reg_output: std_logic_vector(num_bits-1 downto 0); + +begin + + -- Drive output signal. + out_valid <= reg_valid; + out_data <= reg_output; + + -- Synchronous process. + process (clk) is + variable t1, t2, t3: std_logic_vector(num_bits-1 downto 0); + begin + if rising_edge(clk) then + + -- Determine valid output state. + -- Delay by 4*288 clock cycles after re-seeding. + if reg_valid_wait = 4*288 then + reg_valid <= '1'; + end if; + + if reg_valid = '0' then + reg_valid_wait <= reg_valid_wait + 1; + end if; + + if out_ready = '1' or reg_valid = '0' then + + -- Prepare output word. + t1 := reg_state(66-1 downto 66-num_bits) xor + reg_state(93-1 downto 93-num_bits); + t2 := reg_state(162-1 downto 162-num_bits) xor + reg_state(177-1 downto 177-num_bits); + t3 := reg_state(243-1 downto 243-num_bits) xor + reg_state(288-1 downto 288-num_bits); + + reg_output <= t1 xor t2 xor t3; + + -- Update internal state. + t1 := t1 xor (reg_state(91-1 downto 91-num_bits) and + reg_state(92-1 downto 92-num_bits)) xor + reg_state(171-1 downto 171-num_bits); + t2 := t2 xor (reg_state(175-1 downto 175-num_bits) and + reg_state(176-1 downto 176-num_bits)) xor + reg_state(264-1 downto 264-num_bits); + t3 := t3 xor (reg_state(286-1 downto 286-num_bits) and + reg_state(287-1 downto 287-num_bits)) xor + reg_state(69-1 downto 69-num_bits); + + reg_state(93-1 downto 0) <= + reg_state(93-1-num_bits downto 0) & t3; + reg_state(177-1 downto 94-1) <= + reg_state(177-1-num_bits downto 94-1) & t1; + reg_state(288-1 downto 178-1) <= + reg_state(288-1-num_bits downto 178-1) & t2; + + end if; + + -- Re-seed function. + if reseed = '1' then + reg_valid <= '0'; + reg_valid_wait <= (others => '0'); + reg_state <= + ones3 & zeros108 & zeros4 & in_iv & zeros13 & in_key; + end if; + + -- Synchronous reset. + if rst = '1' then + reg_valid <= '0'; + reg_valid_wait <= (others => '0'); + reg_state <= + ones3 & zeros108 & zeros4 & init_iv & zeros13 & init_key; + reg_output <= (others => '0'); + end if; + + end if; + end process; + +end architecture; +