URL
https://opencores.org/ocsvn/BasicRSA/BasicRSA/trunk
Subversion Repositories BasicRSA
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/rtl/vhdl/rsacypher.vhd
0,0 → 1,274
---------------------------------------------------------------------- |
---- ---- |
---- Basic RSA Public Key Cryptography IP Core ---- |
---- ---- |
---- Implementation of BasicRSA IP core according to ---- |
---- BasicRSA IP core specification document. ---- |
---- ---- |
---- To Do: ---- |
---- - ---- |
---- ---- |
---- Author(s): ---- |
---- - Steven R. McQueen, srmcqueen@opencores.org ---- |
---- ---- |
---------------------------------------------------------------------- |
---- ---- |
---- Copyright (C) 2001 Authors and OPENCORES.ORG ---- |
---- ---- |
---- This source file may be used and distributed without ---- |
---- restriction provided that this copyright statement is not ---- |
---- removed from the file and that any derivative work contains ---- |
---- the original copyright notice and the associated disclaimer. ---- |
---- ---- |
---- This source file 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. ---- |
---- ---- |
---- This source is distributed in the hope that it will be ---- |
---- useful, but WITHOUT ANY WARRANTY; without even the implied ---- |
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ---- |
---- PURPOSE. See the GNU Lesser General Public License for more ---- |
---- details. ---- |
---- ---- |
---- You should have received a copy of the GNU Lesser General ---- |
---- Public License along with this source; if not, download it ---- |
---- from http://www.opencores.org/lgpl.shtml ---- |
---- ---- |
---------------------------------------------------------------------- |
-- |
-- CVS Revision History |
-- |
-- $Log: not supported by cvs2svn $ |
-- |
|
-- This module implements the RSA Public Key Cypher. It expects to receive the data block |
-- to be encrypted or decrypted on the indata bus, the exponent to be used on the inExp bus, |
-- and the modulus on the inMod bus. The data block must have a value less than the modulus. |
-- It may be worth noting that in practice the exponent is not restricted to the size of the |
-- modulus, as would be implied by the bus sizes used in this design. This design must |
-- therefore be regarded as a demonstration only. |
-- |
-- A Square-and-Multiply algorithm is used in this module. For each bit of the exponent, the |
-- message value is squared. For each '1' bit of the exponent, the message value is multiplied |
-- by the result of the squaring operation. The operation ends when there are no more '1' |
-- bits in the exponent. Unfortunately, the squaring multiplication must be performed whether |
-- the corresponding exponent bit is '1' or '0', so very little is gained by skipping the |
-- multiplication of the data value. A multiplication is performed for every significant bit |
-- in the exponent. |
-- |
-- Comments, questions and suggestions may be directed to the author at srmcqueen@mcqueentech.com. |
|
|
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_ARITH.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
-- Uncomment the following lines to use the declarations that are |
-- provided for instantiating Xilinx primitive components. |
--library UNISIM; |
--use UNISIM.VComponents.all; |
|
entity RSACypher is |
Generic (KEYSIZE: integer := 32); |
Port (indata: in std_logic_vector(KEYSIZE-1 downto 0); |
inExp: in std_logic_vector(KEYSIZE-1 downto 0); |
inMod: in std_logic_vector(KEYSIZE-1 downto 0); |
cypher: out std_logic_vector(KEYSIZE-1 downto 0); |
clk: in std_logic; |
ds: in std_logic; |
reset: in std_logic; |
ready: out std_logic |
); |
end RSACypher; |
|
architecture Behavioral of RSACypher is |
attribute keep: string; |
|
component modmult is |
Generic (MPWID: integer); |
Port ( mpand : in std_logic_vector(MPWID-1 downto 0); |
mplier : in std_logic_vector(MPWID-1 downto 0); |
modulus : in std_logic_vector(MPWID-1 downto 0); |
product : out std_logic_vector(MPWID-1 downto 0); |
clk : in std_logic; |
ds : in std_logic; |
reset : in std_logic; |
ready: out std_logic); |
end component; |
|
signal modreg: std_logic_vector(KEYSIZE-1 downto 0); -- store the modulus value during operation |
signal root: std_logic_vector(KEYSIZE-1 downto 0); -- value to be squared |
signal square: std_logic_vector(KEYSIZE-1 downto 0); -- result of square operation |
signal sqrin: std_logic_vector(KEYSIZE-1 downto 0); -- 1 or copy of root |
signal tempin: std_logic_vector(KEYSIZE-1 downto 0); -- 1 or copy of square |
signal tempout: std_logic_vector(KEYSIZE-1 downto 0); -- result of multiplication |
signal count: std_logic_vector(KEYSIZE-1 downto 0); -- working copy of exponent |
|
signal multrdy, sqrrdy, bothrdy: std_logic; -- signals to indicate completion of multiplications |
signal multgo, sqrgo: std_logic; -- signals to trigger start of multiplications |
signal done: std_logic; -- signal to indicate encryption complete |
|
-- The following attributes can be set to make signal tracing easier |
|
--attribute keep of multrdy: signal is "true"; |
--attribute keep of sqrrdy: signal is "true"; |
--attribute keep of bothrdy: signal is "true"; |
--attribute keep of multgo: signal is "true"; |
--attribute keep of sqrgo: signal is "true"; |
|
|
begin |
|
ready <= done; |
bothrdy <= multrdy and sqrrdy; |
|
-- Modular multiplier to produce products |
modmultiply: modmult |
Generic Map(MPWID => KEYSIZE) |
Port Map(mpand => tempin, |
mplier => sqrin, |
modulus => modreg, |
product => tempout, |
clk => clk, |
ds => multgo, |
reset => reset, |
ready => multrdy); |
|
-- Modular multiplier to take care of squaring operations |
modsqr: modmult |
Generic Map(MPWID => KEYSIZE) |
Port Map(mpand => root, |
mplier => root, |
modulus => modreg, |
product => square, |
clk => clk, |
ds => multgo, |
reset => reset, |
ready =>sqrrdy); |
|
--counter manager process tracks counter and enable flags |
mngcount: process (clk, reset, done, ds, count, bothrdy) is |
begin |
-- handles DONE and COUNT signals |
|
if reset = '1' then |
count <= (others => '0'); |
done <= '1'; |
elsif rising_edge(clk) then |
if done = '1' then |
if ds = '1' then |
-- first time through |
count <= '0' & inExp(KEYSIZE-1 downto 1); |
done <= '0'; |
end if; |
-- after first time |
elsif count = 0 then |
if bothrdy = '1' and multgo = '0' then |
cypher <= tempout; -- set output value |
done <= '1'; |
end if; |
elsif bothrdy = '1' then |
if multgo = '0' then |
count <= '0' & count(KEYSIZE-1 downto 1); |
end if; |
end if; |
end if; |
|
end process mngcount; |
|
-- This process sets the input values for the squaring multitplier |
setupsqr: process (clk, reset, done, ds) is |
begin |
|
if reset = '1' then |
root <= (others => '0'); |
modreg <= (others => '0'); |
elsif rising_edge(clk) then |
if done = '1' then |
if ds = '1' then |
-- first time through, input is sampled only once |
modreg <= inMod; |
root <= indata; |
end if; |
-- after first time, square result is fed back to multiplier |
else |
root <= square; |
end if; |
end if; |
|
end process setupsqr; |
|
-- This process sets input values for the product multiplier |
setupmult: process (clk, reset, done, ds) is |
begin |
|
if reset = '1' then |
tempin <= (others => '0'); |
sqrin <= (others => '0'); |
modreg <= (others => '0'); |
elsif rising_edge(clk) then |
if done = '1' then |
if ds = '1' then |
-- first time through, input is sampled only once |
-- if the least significant bit of the exponent is '1' then we seed the |
-- multiplier with the message value. Otherwise, we seed it with 1. |
-- The square is set to 1, so the result of the first multiplication will be |
-- either 1 or the initial message value |
if inExp(0) = '1' then |
tempin <= indata; |
else |
tempin(KEYSIZE-1 downto 1) <= (others => '0'); |
tempin(0) <= '1'; |
end if; |
modreg <= inMod; |
sqrin(KEYSIZE-1 downto 1) <= (others => '0'); |
sqrin(0) <= '1'; |
end if; |
-- after first time, the multiplication and square results are fed back through the multiplier. |
-- The counter (exponent) has been shifted one bit to the right |
-- If the least significant bit of the exponent is '1' the result of the most recent |
-- squaring operation is fed to the multiplier. |
-- Otherwise, the square value is set to 1 to indicate no multiplication. |
else |
tempin <= tempout; |
if count(0) = '1' then |
sqrin <= square; |
else |
sqrin(KEYSIZE-1 downto 1) <= (others => '0'); |
sqrin(0) <= '1'; |
end if; |
end if; |
end if; |
|
end process setupmult; |
|
-- this process enables the multipliers when it is safe to do so |
crypto: process (clk, reset, done, ds, count, bothrdy) is |
begin |
|
if reset = '1' then |
multgo <= '0'; |
elsif rising_edge(clk) then |
if done = '1' then |
if ds = '1' then |
-- first time through - automatically trigger first multiplier cycle |
multgo <= '1'; |
end if; |
-- after first time, trigger multipliers when both operations are complete |
elsif count /= 0 then |
if bothrdy = '1' then |
multgo <= '1'; |
end if; |
end if; |
-- when multipliers have been started, disable multiplier inputs |
if multgo = '1' then |
multgo <= '0'; |
end if; |
end if; |
|
end process crypto; |
|
end Behavioral; |
/trunk/rtl/vhdl/Testmult.vhd
0,0 → 1,81
|
-- VHDL Test Bench Created from source file modmult32.vhd -- 18:42:57 05/04/2003 |
-- |
-- Notes: |
-- This testbench has been automatically generated using types std_logic and |
-- std_logic_vector for the ports of the unit under test. Xilinx recommends |
-- that these types always be used for the top-level I/O of a design in order |
-- to guarantee that the testbench will bind correctly to the post-implementation |
-- simulation model. |
-- |
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.numeric_std.ALL; |
|
ENTITY testbench IS |
END testbench; |
|
ARCHITECTURE behavior OF testbench IS |
|
COMPONENT modmult32 |
PORT( |
mpand : IN std_logic_vector(31 downto 0); |
mplier : IN std_logic_vector(31 downto 0); |
modulus : IN std_logic_vector(31 downto 0); |
clk : IN std_logic; |
ds : IN std_logic; |
reset : IN std_logic; |
product : OUT std_logic_vector(31 downto 0); |
ready : OUT std_logic |
); |
END COMPONENT; |
|
SIGNAL mpand : std_logic_vector(31 downto 0); |
SIGNAL mplier : std_logic_vector(31 downto 0); |
SIGNAL modulus : std_logic_vector(31 downto 0); |
SIGNAL product : std_logic_vector(31 downto 0); |
SIGNAL clk : std_logic; |
SIGNAL ds : std_logic; |
SIGNAL reset : std_logic; |
SIGNAL ready : std_logic; |
|
BEGIN |
|
uut: modmult32 PORT MAP( |
mpand => mpand, |
mplier => mplier, |
modulus => modulus, |
product => product, |
clk => clk, |
ds => ds, |
reset => reset, |
ready => ready |
); |
|
|
-- *** Test Bench - User Defined Section *** |
tb : PROCESS |
BEGIN |
reset <= '1'; |
wait until clk = '1'; |
reset <= '0'; |
wait until clk = '0'; |
ds <= '1'; |
mpand <= x"00003285"; |
mplier <= x"00000015"; |
modulus <= x"00007f00"; |
wait; -- will wait forever |
END PROCESS; |
|
clkgen: process |
begin |
wait for 3 ns; |
if clk = '1' then |
clk <= '0'; |
else |
clk <= '1'; |
end if; |
end process; |
-- *** End Test Bench - User Defined Section *** |
|
END; |
/trunk/rtl/vhdl/modmult.vhd
0,0 → 1,166
---------------------------------------------------------------------- |
---- ---- |
---- Modular Multiplier ---- |
---- RSA Public Key Cryptography IP Core ---- |
---- ---- |
---- This file is part of the BasicRSA project ---- |
---- http://www.opencores.org/ ---- |
---- ---- |
---- To Do: ---- |
---- - Speed and efficiency improvements ---- |
---- - Possible revisions for good engineering/coding practices ---- |
---- ---- |
---- Author(s): ---- |
---- - Steven R. McQueen, srmcqueen@opencores.org ---- |
---- ---- |
---------------------------------------------------------------------- |
---- ---- |
---- Copyright (C) 2003 Steven R. McQueen ---- |
---- ---- |
---- This source file may be used and distributed without ---- |
---- restriction provided that this copyright statement is not ---- |
---- removed from the file and that any derivative work contains ---- |
---- the original copyright notice and the associated disclaimer. ---- |
---- ---- |
---- This source file 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. ---- |
---- ---- |
---- This source is distributed in the hope that it will be ---- |
---- useful, but WITHOUT ANY WARRANTY; without even the implied ---- |
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ---- |
---- PURPOSE. See the GNU Lesser General Public License for more ---- |
---- details. ---- |
---- ---- |
---- You should have received a copy of the GNU Lesser General ---- |
---- Public License along with this source; if not, download it ---- |
---- from http://www.opencores.org/lgpl.shtml ---- |
---- ---- |
---------------------------------------------------------------------- |
-- |
-- CVS Revision History |
-- |
-- $Log: not supported by cvs2svn $ |
-- |
|
-- This module implements the modular multiplier for the RSA Public Key Cypher. It expects |
-- to receive a multiplicand on th MPAND bus, a multiplier on the MPLIER bus, and a modulus |
-- on the MODULUS bus. The multiplier and multiplicand must have a value less than the modulus. |
-- |
-- A Shift-and-Add algorithm is used in this module. For each bit of the multiplier, the |
-- multiplicand value is shifted. For each '1' bit of the multiplier, the shifted multiplicand |
-- value is added to the product. To ensure that the product is always expressed as a remainder |
-- two subtractions are performed on the product, P2 = P1-modulus, and P3 = P1-(2*modulus). |
-- The high-order bits of these results are used to determine whether P sould be copied from |
-- P1, P2, or P3. |
-- |
-- The operation ends when all '1' bits in the multiplier have been used. |
-- |
-- Comments, questions and suggestions may be directed to the author at srmcqueen@mcqueentech.com. |
|
|
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_ARITH.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
-- Uncomment the following lines to use the declarations that are |
-- provided for instantiating Xilinx primitive components. |
--library UNISIM; |
--use UNISIM.VComponents.all; |
|
entity modmult is |
Generic (MPWID: integer := 32); |
Port ( mpand : in std_logic_vector(MPWID-1 downto 0); |
mplier : in std_logic_vector(MPWID-1 downto 0); |
modulus : in std_logic_vector(MPWID-1 downto 0); |
product : out std_logic_vector(MPWID-1 downto 0); |
clk : in std_logic; |
ds : in std_logic; |
reset : in std_logic; |
ready : out std_logic); |
end modmult; |
|
architecture modmult1 of modmult is |
|
signal mpreg: std_logic_vector(MPWID-1 downto 0); |
signal mcreg, mcreg1, mcreg2: std_logic_vector(MPWID+1 downto 0); |
signal modreg1, modreg2: std_logic_vector(MPWID+1 downto 0); |
signal prodreg, prodreg1, prodreg2, prodreg3, prodreg4: std_logic_vector(MPWID+1 downto 0); |
|
--signal count: integer; |
signal modstate: std_logic_vector(1 downto 0); |
signal first: std_logic; |
|
begin |
|
-- final result... |
product <= prodreg4(MPWID-1 downto 0); |
|
-- add shifted value if place bit is '1', copy original if place bit is '0' |
with mpreg(0) select |
prodreg1 <= prodreg + mcreg when '1', |
prodreg when others; |
|
-- subtract modulus and subtract modulus * 2. |
prodreg2 <= prodreg1 - modreg1; |
prodreg3 <= prodreg1 - modreg2; |
|
-- negative results mean that we subtracted too much... |
modstate <= prodreg3(mpwid+1) & prodreg2(mpwid+1); |
|
-- select the correct modular result and copy it.... |
with modstate select |
prodreg4 <= prodreg1 when "11", |
prodreg2 when "10", |
prodreg3 when others; |
|
-- meanwhile, subtract the modulus from the shifted multiplicand... |
mcreg1 <= mcreg - modreg1; |
|
-- select the correct modular value and copy it. |
with mcreg1(MPWID) select |
mcreg2 <= mcreg when '1', |
mcreg1 when others; |
|
ready <= first; |
|
combine: process (clk, first, ds, mpreg, reset) is |
|
begin |
|
if reset = '1' then |
first <= '1'; |
elsif rising_edge(clk) then |
if first = '1' then |
-- First time through, set up registers to start multiplication procedure |
-- Input values are sampled only once |
if ds = '1' then |
mpreg <= mplier; |
mcreg <= "00" & mpand; |
modreg1 <= "00" & modulus; |
modreg2 <= '0' & modulus & '0'; |
prodreg <= (others => '0'); |
first <= '0'; |
end if; |
else |
-- when all bits have been shifted out of the multiplicand, operation is over |
-- Note: this leads to at least one waste cycle per multiplication |
if mpreg = 0 then |
first <= '1'; |
else |
-- shift the multiplicand left one bit |
mcreg <= mcreg2(MPWID downto 0) & '0'; |
-- shift the multiplier right one bit |
mpreg <= '0' & mpreg(MPWID-1 downto 1); |
-- copy intermediate product |
prodreg <= prodreg4; |
end if; |
end if; |
end if; |
|
end process combine; |
|
end modmult1; |
/trunk/rtl/vhdl/rsatest16.vhd
0,0 → 1,92
|
-- VHDL Test Bench Created from source file rsacypher.vhd -- 13:35:16 05/04/2003 |
-- |
-- Notes: |
-- This testbench has been automatically generated using types std_logic and |
-- std_logic_vector for the ports of the unit under test. Xilinx recommends |
-- that these types always be used for the top-level I/O of a design in order |
-- to guarantee that the testbench will bind correctly to the post-implementation |
-- simulation model. |
-- |
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.numeric_std.ALL; |
|
ENTITY testbench IS |
END testbench; |
|
ARCHITECTURE behavior OF testbench IS |
|
COMPONENT rsacypher |
PORT( |
indata : IN std_logic_vector(31 downto 0); |
inexp : IN std_logic_vector(31 downto 0); |
inmod : IN std_logic_vector(31 downto 0); |
clk : IN std_logic; |
ds : IN std_logic; |
reset : IN std_logic; |
cypher : OUT std_logic_vector(31 downto 0); |
ready : OUT std_logic |
); |
END COMPONENT; |
|
SIGNAL indata : std_logic_vector(31 downto 0); |
SIGNAL inexp : std_logic_vector(31 downto 0); |
SIGNAL inmod : std_logic_vector(31 downto 0); |
SIGNAL cypher : std_logic_vector(31 downto 0); |
SIGNAL clk : std_logic; |
SIGNAL ds : std_logic; |
SIGNAL reset : std_logic; |
SIGNAL ready : std_logic; |
|
BEGIN |
|
uut: rsacypher PORT MAP( |
indata => indata, |
inexp => inexp, |
inmod => inmod, |
cypher => cypher, |
clk => clk, |
ds => ds, |
reset => reset, |
ready => ready |
); |
|
|
-- *** Test Bench - User Defined Section *** |
TB: PROCESS |
BEGIN |
wait for 120ns; |
reset <= '1'; |
ds <= '0'; |
wait for 20ns; |
wait until clk = '0'; |
reset <= '0'; |
wait until clk = '1'; |
wait until clk = '0'; |
inexp <= x"00903ad9"; |
inmod <= x"03b2c159"; |
indata <= x"00724183"; |
wait until clk = '1'; |
wait for 2ns; |
ds <= '1'; |
wait until ready = '0'; |
ds <= '0'; |
wait until ready = '1'; |
wait; |
-- decrypt exponent inexp <= x"02d80e39"; |
END PROCESS; |
|
|
ClkGen : PROCESS |
BEGIN |
wait for 5300ps; -- will wait forever |
if clk = '1' then |
clk <= '0'; |
else |
clk <= '1'; |
end if; |
END PROCESS; |
-- *** End Test Bench - User Defined Section *** |
|
END; |