Skip to content

Commit

Permalink
[otbn] Updated uRNG in OTBN
Browse files Browse the repository at this point in the history
Replaced OTBN's LFSR-based PRNG with xoshiro256pp.

Signed-off-by: Vladimir Rozic <[email protected]>
  • Loading branch information
vrozic authored and GregAC committed Nov 12, 2021
1 parent 2796f45 commit dd3a05b
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 163 deletions.
12 changes: 2 additions & 10 deletions hw/ip/otbn/data/otbn.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,14 @@
local: "false",
expose: "true"
},
{ name: "RndCnstUrndLfsrSeed",
type: "otbn_pkg::urnd_lfsr_seed_t",
{ name: "RndCnstUrndPrngSeed",
type: "otbn_pkg::urnd_prng_seed_t",
desc: '''
Default seed of the PRNG used for URND.
'''
randcount: "256",
randtype: "data"
},
{ name: "RndCnstUrndChunkLfsrPerm",
type: "otbn_pkg::urnd_chunk_lfsr_perm_t",
desc: '''
Permutation applied to the LFSR chunks of the PRNG used for URND.
'''
randcount: "64",
randtype: "perm"
},
{ name: "RndCnstOtbnKey",
type: "otp_ctrl_pkg::otbn_key_t",
desc: '''
Expand Down
1 change: 1 addition & 0 deletions hw/ip/otbn/otbn.core
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ filesets:
- lowrisc:prim:assert
- lowrisc:prim:util
- lowrisc:prim:lfsr
- lowrisc:prim:xoshiro256pp
- lowrisc:prim:cipher_pkg
- lowrisc:prim:mubi
- lowrisc:ip:edn_pkg
Expand Down
11 changes: 4 additions & 7 deletions hw/ip/otbn/rtl/otbn.sv
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ module otbn
parameter regfile_e RegFile = RegFileFF,
parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}},

// Default seed and permutation for URND LFSR
parameter urnd_lfsr_seed_t RndCnstUrndLfsrSeed = RndCnstUrndLfsrSeedDefault,
parameter urnd_chunk_lfsr_perm_t RndCnstUrndChunkLfsrPerm = RndCnstUrndChunkLfsrPermDefault,
// Default seed for URND PRNG
parameter urnd_prng_seed_t RndCnstUrndPrngSeed = RndCnstUrndPrngSeedDefault,

// Default seed and nonce for scrambling
parameter otp_ctrl_pkg::otbn_key_t RndCnstOtbnKey = RndCnstOtbnKeyDefault,
Expand Down Expand Up @@ -835,8 +834,7 @@ module otbn
.RegFile(RegFile),
.DmemSizeByte(DmemSizeByte),
.ImemSizeByte(ImemSizeByte),
.RndCnstUrndLfsrSeed(RndCnstUrndLfsrSeed),
.RndCnstUrndChunkLfsrPerm(RndCnstUrndChunkLfsrPerm)
.RndCnstUrndPrngSeed(RndCnstUrndPrngSeed)
) u_otbn_core (
.clk_i,
.rst_ni (rst_n),
Expand Down Expand Up @@ -885,8 +883,7 @@ module otbn
.RegFile(RegFile),
.DmemSizeByte(DmemSizeByte),
.ImemSizeByte(ImemSizeByte),
.RndCnstUrndLfsrSeed(RndCnstUrndLfsrSeed),
.RndCnstUrndChunkLfsrPerm(RndCnstUrndChunkLfsrPerm)
.RndCnstUrndPrngSeed(RndCnstUrndPrngSeed)
) u_otbn_core (
.clk_i,
.rst_ni (rst_n),
Expand Down
8 changes: 3 additions & 5 deletions hw/ip/otbn/rtl/otbn_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ module otbn_core
// Enable internal secure wipe
parameter bit SecWipeEn = 1'b0,

// Default seed and permutation for URND LFSR
parameter urnd_lfsr_seed_t RndCnstUrndLfsrSeed = RndCnstUrndLfsrSeedDefault,
parameter urnd_chunk_lfsr_perm_t RndCnstUrndChunkLfsrPerm = RndCnstUrndChunkLfsrPermDefault,
// Default seed for URND PRNG
parameter urnd_prng_seed_t RndCnstUrndPrngSeed = RndCnstUrndPrngSeedDefault,

localparam int ImemAddrWidth = prim_util_pkg::vbits(ImemSizeByte),
localparam int DmemAddrWidth = prim_util_pkg::vbits(DmemSizeByte)
Expand Down Expand Up @@ -582,8 +581,7 @@ module otbn_core
);

otbn_rnd #(
.RndCnstUrndLfsrSeed (RndCnstUrndLfsrSeed),
.RndCnstUrndChunkLfsrPerm (RndCnstUrndChunkLfsrPerm)
.RndCnstUrndPrngSeed (RndCnstUrndPrngSeed)
) u_otbn_rnd (
.clk_i,
.rst_ni,
Expand Down
21 changes: 5 additions & 16 deletions hw/ip/otbn/rtl/otbn_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -398,25 +398,14 @@ package otbn_pkg;
OtbnStartStopSecureWipeComplete
} otbn_start_stop_state_e;

// URNG PRNG default LFSR seed and permutation
// A single default seed is split into 64 bit chunks, a separate LFSR is used for each chunk. All
// LFSR chunks use the same permutation.
// These LFSR parameters have been generated with
// URNG PRNG default seed.
// These parameters have been generated with
// $ ./util/design/gen-lfsr-seed.py --width 256 --seed 2840984437 --prefix "Urnd"
parameter int UrndLfsrWidth = 256;
typedef logic [UrndLfsrWidth-1:0] urnd_lfsr_seed_t;
parameter urnd_lfsr_seed_t RndCnstUrndLfsrSeedDefault =
parameter int UrndPrngWidth = 256;
typedef logic [UrndPrngWidth-1:0] urnd_prng_seed_t;
parameter urnd_prng_seed_t RndCnstUrndPrngSeedDefault =
256'h84ddfadaf7e1134d70aa1c59de6197ff25a4fe335d095f1e2cba89acbe4a07e9;

// These LFSR parameters have been generated with
// $ ./util/design/gen-lfsr-seed.py --width 64 --seed 2840984437 --prefix "UrndChunk"
parameter int UrndChunkLfsrWidth = 64;
typedef logic [UrndChunkLfsrWidth-1:0][$clog2(UrndChunkLfsrWidth)-1:0] urnd_chunk_lfsr_perm_t;
parameter urnd_chunk_lfsr_perm_t RndCnstUrndChunkLfsrPermDefault = {
128'h911992e063cafd4f3b13ee5682b969be,
256'h86c701ecc39d9d483bdcacb5a15340b0988e2336e955ddd0dc01ab17e173726e
};

parameter otp_ctrl_pkg::otbn_key_t RndCnstOtbnKeyDefault =
128'h14e8cecae3040d5e12286bb3cc113298;
parameter otp_ctrl_pkg::otbn_nonce_t RndCnstOtbnNonceDefault =
Expand Down
73 changes: 23 additions & 50 deletions hw/ip/otbn/rtl/otbn_rnd.sv
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*
* This module implements the RND, RND_PREFETCH and URND CSRs/WSRs. The EDN (entropy distribution
* network) provides the bits for random numbers. RND gives direct access to EDN bits. URND provides
* bits from an LFSR that is seeded with bits from the EDN.
* bits from a PRNG that is seeded with bits from the EDN.
*/

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -23,8 +23,7 @@

module otbn_rnd import otbn_pkg::*;
#(
parameter urnd_lfsr_seed_t RndCnstUrndLfsrSeed = RndCnstUrndLfsrSeedDefault,
parameter urnd_chunk_lfsr_perm_t RndCnstUrndChunkLfsrPerm = RndCnstUrndChunkLfsrPermDefault
parameter urnd_prng_seed_t RndCnstUrndPrngSeed = RndCnstUrndPrngSeedDefault
) (
input logic clk_i,
input logic rst_ni,
Expand All @@ -34,14 +33,14 @@ module otbn_rnd import otbn_pkg::*;
output logic rnd_valid_o,
output logic [WLEN-1:0] rnd_data_o,

// Request URND LFSR reseed from the EDN
// Request URND PRNG reseed from the EDN
input logic urnd_reseed_req_i,
// Remains asserted whilst reseed is in progress
output logic urnd_reseed_busy_o,
// When asserted URND LFSR state advances. It is permissible to advance the state whilst
// When asserted PRNG state advances. It is permissible to advance the state whilst
// reseeding.
input logic urnd_advance_i,
// URND data from LFSR
// URND data from PRNG
output logic [WLEN-1:0] urnd_data_o,

// Entropy distribution network (EDN)
Expand All @@ -53,9 +52,6 @@ module otbn_rnd import otbn_pkg::*;
input logic edn_urnd_ack_i,
input logic [EdnDataWidth-1:0] edn_urnd_data_i
);
// Determine how many LFSR chunks are required to fill a full WLEN register
localparam int LfsrChunksPerWLEN = WLEN / UrndChunkLfsrWidth;
localparam int BytesPerLfsrChunk = UrndChunkLfsrWidth / 8;

logic rnd_valid_q, rnd_valid_d;
logic [WLEN-1:0] rnd_data_q, rnd_data_d;
Expand Down Expand Up @@ -109,7 +105,7 @@ module otbn_rnd import otbn_pkg::*;
assign rnd_data_o = rnd_data_q;

/////////////////////////
// URND Implementation //
// PRNG Implementation //
/////////////////////////

logic edn_urnd_req_complete;
Expand All @@ -129,46 +125,23 @@ module otbn_rnd import otbn_pkg::*;
end
end

logic lfsr_seed_en;
logic [UrndChunkLfsrWidth-1:0] lfsr_seed [LfsrChunksPerWLEN];
logic [UrndChunkLfsrWidth-1:0] lfsr_state [LfsrChunksPerWLEN];

assign lfsr_seed_en = edn_urnd_req_complete;

// We use multiple LFSR instances each having a width of ChunkSize.
// This is a functional prototype of the final URND functionality and is subject to change
// https://github.com/lowRISC/opentitan/issues/6083
for (genvar c = 0; c < LfsrChunksPerWLEN; c++) begin : gen_lfsr_chunks
localparam logic [UrndChunkLfsrWidth-1:0] LfsrChunkSeed =
RndCnstUrndLfsrSeed[c * UrndChunkLfsrWidth +: UrndChunkLfsrWidth];

assign lfsr_seed[c] = edn_urnd_data_i[c * UrndChunkLfsrWidth+: UrndChunkLfsrWidth];

prim_lfsr #(
.LfsrType ( "GAL_XOR" ),
.LfsrDw ( UrndChunkLfsrWidth ),
.StateOutDw ( UrndChunkLfsrWidth ),
.DefaultSeed ( LfsrChunkSeed ),
.StatePermEn ( 1'b1 ),
.StatePerm ( RndCnstUrndChunkLfsrPerm )
) u_lfsr_chunk (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.seed_en_i ( lfsr_seed_en ),
.seed_i ( lfsr_seed[c] ),
.lfsr_en_i ( urnd_advance_i ),
.entropy_i ( '0 ),
.state_o ( lfsr_state[c] )
);
end

// Further "scramble" the LFSR state at the byte level to break linear shift patterns.
for (genvar c = 0; c < LfsrChunksPerWLEN; c++) begin : gen_lfsr_state_scramble_outer
for (genvar b = 0;b < BytesPerLfsrChunk; b++) begin : gen_lfsr_start_scramble_inner
assign urnd_data_o[b * 8 + c * UrndChunkLfsrWidth +: 8] =
prim_cipher_pkg::sbox4_8bit(lfsr_state[c][b*8 +: 8], prim_cipher_pkg::PRINCE_SBOX4);
end
end
logic xoshiro_seed_en;

assign xoshiro_seed_en = edn_urnd_req_complete;

prim_xoshiro256pp #(
.OutputDw (WLEN),
.DefaultSeed(RndCnstUrndPrngSeed)
) u_xoshiro256pp(
.clk_i,
.rst_ni,
.seed_en_i (xoshiro_seed_en),
.seed_i (edn_urnd_data_i),
.xoshiro_en_i (urnd_advance_i),
.entropy_i ('0),
.data_o (urnd_data_o),
.all_zero_o ()
);

`ASSERT(rnd_clear_on_req_complete, rnd_req_complete |=> ~rnd_valid_q)
endmodule
Loading

0 comments on commit dd3a05b

Please sign in to comment.