Obfuscating VHDL Code

Semantic Designs can construct custom obfuscators for virtually any source language as a part of the corresponding Source Formatter. This page contains VHDL sample code, its obfuscated version, and the generated obfuscation map.

VHDL Sample Code before Obfuscation

(This is the same formatted code shown on the VHDL Formatter example page)

USE work.multiplier_types.all;
USE work.bv_arithmetic.all;
USE std.textio.all;

ENTITY multiplier IS
  PORT ( clk :          in  bit;
         load :         in  bit;
         multiplicand : in  word;
         multiply_by :   in  word;
         ready :        out bit;
         product_low :  inout word;
         product_high : inout word );
END multiplier;


ARCHITECTURE mixed OF multiplier IS

  COMPONENT reg_1
    PORT ( clk :        in  bit;
           load :       in  bit;
           d :          in  bit;
           q :          out bit );
  END COMPONENT;

  COMPONENT shift_reg_word
    PORT ( clk :        in  bit;
           load :       in  bit;
           shift :      in  bit;
           clr :        in  bit;
           d :          in  word;
           d_s :        in  bit;
           q :          out word;
           q_s :        out bit );
  END COMPONENT;

  COMPONENT reg_word
    PORT ( clk :        in  bit;
           load :       in  bit;
           d :          in  word;
           q :          out word);
  END COMPONENT;

  COMPONENT adder
    PORT ( a :          in  word;
           b :          in  word;
           c_in :       in  bit;
           s :          out word;
           c_out :      out bit);
  END COMPONENT;

  COMPONENT and_word
    PORT ( a :  in  bit;
           b :  in  word;
           z :  out word);
  END COMPONENT;

  SIGNAL b : word;
  SIGNAL b_or_0 : word;
  SIGNAL partial_product : word;
  SIGNAL c_in : bit;
  SIGNAL c_out : bit;
  SIGNAL c_to_p : bit;
  SIGNAL p_to_a : bit;

  SIGNAL p_and_c_load : bit;
  SIGNAL shift : bit;
  SIGNAL tied_0 : bit := '0';

  ALIAS a_0 : bit IS product_low(0);

BEGIN  --  mixed

  a_reg : shift_reg_word
    port map ( clk      => clk,
               load     => load,
               shift    => shift,
               clr      => tied_0,
               d        => multiplicand,
               d_s      => p_to_a,
               q        => product_low,
               q_s      => open );

  b_reg : reg_word
    port map ( clk      => clk,
               load     => load,
               d        => multiply_by,
               q        => b );

  p_reg : shift_reg_word
    port map ( clk      => clk,
               load     => p_and_c_load,
               shift    => shift,
               clr      => load,
               d        => partial_product,
               d_s      => c_in,
               q        => product_high,
               q_s      => p_to_a );

  carry_reg : reg_1
    port map (clk       => clk,
              load      => p_and_c_load,
              d         => c_out,
              q         => c_in );

  b_gate : and_word
    port map ( a        => a_0,
               b        => b,
               z        => b_or_0 );

  the_adder : adder
    port map ( a        => product_high,
               b        => b_or_0,
               c_in     => c_in,
               s        => partial_product,
               c_out    => c_out );

  -----------------------------------------------------------------------------
  --  Process:   controller
  --  Purpose:  sequences register loading and shifting
  --  Inputs:   clk, load
  --  Outputs:  p_and_c_load, shift, ready
  -----------------------------------------------------------------------------
  controller : PROCESS
    CONSTANT Tpd_clk_load : Time := 5 ns;
    CONSTANT Tpd_clk_shift : Time := 5 ns;
    CONSTANT Tpd_clk_ready : Time := 5 ns;
  BEGIN  --  PROCESS controller
    p_and_c_load <= '0' after Tpd_Clk_Load;
    shift <= '0' after Tpd_clk_shift;
    ready <= '1' after Tpd_clk_ready;
    WAIT on clk until clk = '1' and load = '1';
    ready <= '0' after Tpd_clk_ready;
    FOR cycle IN 1 to word_size LOOP
      p_and_c_load <= '1' after Tpd_clk_load;
      WAIT until clk = '1';
      p_and_c_load <= '0' after Tpd_clk_load;
      shift <= '1' after Tpd_clk_shift;
      WAIT until clk = '1';
      shift <= '0' after Tpd_clk_shift;
    END LOOP;                            --  cycle
    ready <= '1' after Tpd_clk_ready;
  END PROCESS controller;

END mixed;

VHDL Code after Obfuscation

Notice that comments are gone, names have been scrambled. The obfuscator uses a special list provided by the user to define names that should be preserved, ensuring that public interfaces and accesses to public libraries remain valid. If you obfuscate a set of VHDL source files simultaneously, only the public symbols they collectively offer will be sensibly named in the source files.

use l.O.all;
use l.l1.all;
use std.textio.all;
entity multiplier is
port (clk: in bit;
      load: in bit;
      multiplicand: in word;
      multiply_by: in word;
      ready: out bit;
      product_low: inout word;
      product_high: inout word);
end multiplier;
architecture O0 of multiplier is
component ll1
port (clk: in bit;
      load: in bit;
      OO0: in bit;
      l11: out bit);
end component;
component O00
port (clk: in bit;
      load: in bit;
      lll1: in bit;
      OOO0: in bit;
      OO0: in word;
      l1l1: in bit;
      l11: out word;
      O0O0: out bit);
end component;
component ll11
port (clk: in bit;
      load: in bit;
      OO0: in word;
      l11: out word);
end component;
component OO00
port (l111: in word;
      O000: in word;
      llll1: in bit;
      OOOO0: out word;
      l1ll1: out bit);
end component;
component O0OO0
port (l111: in bit;
      O000: in word;
      ll1l1: out word);
end component;
signal O000: word;
signal OO0O0: word;
signal l11l1: word;
signal llll1: bit;
signal l1ll1: bit;
signal O00O0: bit;
signal lll11: bit;
signal OOO00: bit;
signal lll1: bit;
signal l1l11: bit := '0';
alias O0O00: bit is product_low(0);
begin
ll111: O00 port map (clk => clk,load => load,lll1 => lll1,OOO0 => l1l11,OO0 => multiplicand,l1l1 => lll11,l11 => product_low,O0O0 => open );
OO000: ll11 port map (clk => clk,load => load,OO0 => multiply_by,l11 => O000);
l1111: O00 port map (clk => clk,load => OOO00,lll1 => lll1,OOO0 => load,OO0 => l11l1,l1l1 => llll1,l11 => product_high,O0O0 => lll11);
O0000: ll1 port map (clk => clk,load => OOO00,OO0 => l1ll1,l11 => llll1);
lllll1: O0OO0 port map (l111 => O0O00,O000 => O000,ll1l1 => OO0O0);
OOOOO0: OO00 port map (l111 => product_high,O000 => OO0O0,llll1 => llll1,OOOO0 => l11l1,l1ll1 => l1ll1);
l1lll1:
process is
constant O0OOO0: ll1ll1 := 5 OO0OO0;
constant l11ll1: ll1ll1 := 5 OO0OO0;
constant O00OO0: ll1ll1 := 5 OO0OO0;
begin
OOO00 <= '0' after O0OOO0;
lll1 <= '0' after l11ll1;
ready <= '1' after O00OO0;
wait on clk until clk = '1' and load = '1';
ready <= '0' after O00OO0;
for lll1l1 in 1 to OOO0O0
loop
OOO00 <= '1' after O0OOO0;
wait until clk = '1';
OOO00 <= '0' after O0OOO0;
lll1 <= '1' after l11ll1;
wait until clk = '1';
lll1 <= '0' after l11ll1;
end loop;
ready <= '1' after O00OO0;
end process l1lll1;
end O0;

Obfuscated Symbol Cross Reference

The obfuscator produces a cross reference mapping obfuscated symbols to the orginal symbols, so that obfuscated code in the field can still be decoded if necessary. In fact, by reversing this map, the obfuscator can unobfuscate the code (of course, it cannot restore the comments).

### Obfuscated Identifiers ###
a -> l111
a_0 -> O0O00
a_reg -> ll111
adder -> OO00
and_word -> O0OO0
b -> O000
b_gate -> lllll1
b_or_0 -> OO0O0
b_reg -> OO000
bv_arithmetic -> l1
c_in -> llll1
c_out -> l1ll1
c_to_p -> O00O0
carry_reg -> O0000
clr -> OOO0
controller -> l1lll1
cycle -> lll1l1
d -> OO0
d_s -> l1l1
mixed -> O0
multiplier_types -> O
ns -> OO0OO0
p_and_c_load -> OOO00
p_reg -> l1111
p_to_a -> lll11
partial_product -> l11l1
q -> l11
q_s -> O0O0
reg_1 -> ll1
reg_word -> ll11
s -> OOOO0
shift -> lll1
shift_reg_word -> O00
the_adder -> OOOOO0
tied_0 -> l1l11
time -> ll1ll1
tpd_clk_load -> O0OOO0
tpd_clk_ready -> O00OO0
tpd_clk_shift -> l11ll1
word_size -> OOO0O0
work -> l
z -> ll1l1

### Preserved Identifiers ###
bit -> bit
clk -> clk
load -> load
multiplicand -> multiplicand
multiplier -> multiplier
multiply_by -> multiply_by
product_high -> product_high
product_low -> product_low
ready -> ready
std -> std
textio -> textio
word -> word
For more information: [email protected]    Follow us at Twitter: @SemanticDesigns

VHDL Obfuscation
Example