|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | // | 
|  | // AES package | 
|  |  | 
|  | package aes_pkg; | 
|  |  | 
|  | // If this parameter is set, fatal alerts clear all status and trigger bits to zero. By | 
|  | // default, it's not set, i.e., no clearing is happening, in order to simplify debugging. | 
|  | parameter bit ClearStatusOnFatalAlert = 1'b0; | 
|  |  | 
|  | // The initial key is always provided in two shares, independently whether the cipher core is | 
|  | // masked or not. | 
|  | parameter int unsigned NumSharesKey = 2; | 
|  |  | 
|  | // Software updates IV in chunks of 32 bits, the counter updates 16 bits at a time. | 
|  | parameter int unsigned SliceSizeCtr = 16; | 
|  | parameter int unsigned NumSlicesCtr = aes_reg_pkg::NumRegsIv * 32 / SliceSizeCtr; | 
|  | parameter int unsigned SliceIdxWidth = prim_util_pkg::vbits(NumSlicesCtr); | 
|  |  | 
|  | // Widths of signals carrying pseudo-random data for clearing | 
|  | parameter int unsigned WidthPRDClearing = 64; | 
|  | parameter int unsigned NumChunksPRDClearing128 = 128/WidthPRDClearing; | 
|  | parameter int unsigned NumChunksPRDClearing256 = 256/WidthPRDClearing; | 
|  |  | 
|  | // Widths of signals carrying pseudo-random data for masking | 
|  | parameter int unsigned WidthPRDSBox     = 8;  // Number PRD bits per S-Box. This includes the | 
|  | // 8 bits for the output mask when using any of the | 
|  | // masked Canright S-Box implementations. | 
|  | parameter int unsigned WidthPRDData     = 16*WidthPRDSBox; // 16 S-Boxes for the data path | 
|  | parameter int unsigned WidthPRDKey      = 4*WidthPRDSBox;  // 4 S-Boxes for the key expand | 
|  | parameter int unsigned WidthPRDMasking  = WidthPRDData + WidthPRDKey; | 
|  |  | 
|  | parameter int unsigned ChunkSizePRDMasking = WidthPRDMasking/5; | 
|  |  | 
|  | // Clearing PRNG default LFSR seed and permutation | 
|  | // These LFSR parameters have been generated with | 
|  | // $ util/design/gen-lfsr-seed.py --width 64 --seed 31468618 --prefix "Clearing" | 
|  | parameter int ClearingLfsrWidth = 64; | 
|  | typedef logic [ClearingLfsrWidth-1:0] clearing_lfsr_seed_t; | 
|  | typedef logic [ClearingLfsrWidth-1:0][$clog2(ClearingLfsrWidth)-1:0] clearing_lfsr_perm_t; | 
|  | parameter clearing_lfsr_seed_t RndCnstClearingLfsrSeedDefault = 64'hc32d580f74f1713a; | 
|  | parameter clearing_lfsr_perm_t RndCnstClearingLfsrPermDefault = { | 
|  | 128'hb33fdfc81deb6292c21f8a3102585067, | 
|  | 256'h9c2f4be1bbe937b4b7c9d7f4e57568d99c8ae291a899143e0d8459d31b143223 | 
|  | }; | 
|  | // A second permutation is needed for the second share. | 
|  | parameter clearing_lfsr_perm_t RndCnstClearingSharePermDefault = { | 
|  | 128'hf66fd61b27847edc2286706fb3a2e900, | 
|  | 256'h9736b95ac3f3b5205caf8dc536aad73605d393c8dd94476e830e97891d4828d0 | 
|  | }; | 
|  |  | 
|  | // Masking PRNG default LFSR seed and permutation | 
|  | // We use a single seed that is split down into chunks internally. | 
|  | // These LFSR parameters have been generated with | 
|  | // $ util/design/gen-lfsr-seed.py --width 160 --seed 31468618 --prefix "Masking" | 
|  | parameter int MaskingLfsrWidth = 160; // = WidthPRDMasking = WidthPRDSBox * (16 + 4) | 
|  | typedef logic [MaskingLfsrWidth-1:0] masking_lfsr_seed_t; | 
|  | typedef logic [MaskingLfsrWidth-1:0][$clog2(MaskingLfsrWidth)-1:0] masking_lfsr_perm_t; | 
|  | parameter masking_lfsr_seed_t RndCnstMaskingLfsrSeedDefault = | 
|  | 160'hc132b5723c5a4cf4743b3c7c32d580f74f1713a; | 
|  | parameter masking_lfsr_perm_t RndCnstMaskingLfsrPermDefault = { | 
|  | 256'h17261943423e4c5c03872194050c7e5f8497081d96666d406f4b606473303469, | 
|  | 256'h8e7c721c8832471f59919e0b128f067b25622768462e554d8970815d490d7f44, | 
|  | 256'h048c867d907a239b20220f6c79071a852d76485452189f14091b1e744e396737, | 
|  | 256'h4f785b772b352f6550613c58130a8b104a3f28019c9a380233956b00563a512c, | 
|  | 256'h808d419d63982a16995e0e3b57826a36718a9329452492533d83115a75316e15 | 
|  | }; | 
|  |  | 
|  | typedef enum integer { | 
|  | SBoxImplLut,                   // Unmasked LUT-based S-Box | 
|  | SBoxImplCanright,              // Unmasked Canright S-Box, see aes_sbox_canright.sv | 
|  | SBoxImplCanrightMasked,        // First-order masked Canright S-Box | 
|  | // see aes_sbox_canright_masked.sv | 
|  | SBoxImplCanrightMaskedNoreuse, // First-order masked Canright S-Box without mask reuse, | 
|  | // see aes_sbox_canright_masked_noreuse.sv | 
|  | SBoxImplDom                    // First-order masked S-Box using domain-oriented masking, | 
|  | // see aes_sbox_canright_dom.sv | 
|  | } sbox_impl_e; | 
|  |  | 
|  |  | 
|  | // Parameters used for controlgroups in the coverage | 
|  | parameter int AES_OP_WIDTH             = 2; | 
|  | parameter int AES_MODE_WIDTH           = 6; | 
|  | parameter int AES_KEYLEN_WIDTH         = 3; | 
|  | parameter int AES_PRNGRESEEDRATE_WIDTH = 3; | 
|  |  | 
|  | // SEC_CM: MAIN.CONFIG.SPARSE | 
|  | typedef enum logic [AES_OP_WIDTH-1:0] { | 
|  | AES_ENC = 2'b01, | 
|  | AES_DEC = 2'b10 | 
|  | } aes_op_e; | 
|  |  | 
|  | // SEC_CM: MAIN.CONFIG.SPARSE | 
|  | typedef enum logic [AES_MODE_WIDTH-1:0] { | 
|  | AES_ECB  = 6'b00_0001, | 
|  | AES_CBC  = 6'b00_0010, | 
|  | AES_CFB  = 6'b00_0100, | 
|  | AES_OFB  = 6'b00_1000, | 
|  | AES_CTR  = 6'b01_0000, | 
|  | AES_NONE = 6'b10_0000 | 
|  | } aes_mode_e; | 
|  |  | 
|  | typedef enum logic [AES_OP_WIDTH-1:0] { | 
|  | CIPH_FWD = 2'b01, | 
|  | CIPH_INV = 2'b10 | 
|  | } ciph_op_e; | 
|  |  | 
|  | // SEC_CM: MAIN.CONFIG.SPARSE | 
|  | typedef enum logic [AES_KEYLEN_WIDTH-1:0] { | 
|  | AES_128 = 3'b001, | 
|  | AES_192 = 3'b010, | 
|  | AES_256 = 3'b100 | 
|  | } key_len_e; | 
|  |  | 
|  | // SEC_CM: MAIN.CONFIG.SPARSE | 
|  | typedef enum logic [AES_PRNGRESEEDRATE_WIDTH-1:0] { | 
|  | PER_1  = 3'b001, | 
|  | PER_64 = 3'b010, | 
|  | PER_8K = 3'b100 | 
|  | } prs_rate_e; | 
|  | parameter int unsigned BlockCtrWidth = 13; | 
|  |  | 
|  | typedef struct packed { | 
|  | logic [31:7] unused; | 
|  | logic        alert_fatal_fault; | 
|  | logic        alert_recov_ctrl_update_err; | 
|  | logic        input_ready; | 
|  | logic        output_valid; | 
|  | logic        output_lost; | 
|  | logic        stall; | 
|  | logic        idle; | 
|  | } status_t; | 
|  |  | 
|  | typedef struct packed { | 
|  | logic        recov_ctrl_update_err; | 
|  | logic        fatal_fault; | 
|  | } alert_test_t; | 
|  |  | 
|  | // Sparse state encodings | 
|  |  | 
|  | // Encoding generated with: | 
|  | // $ ./util/design/sparse-fsm-encode.py -d 3 -m 8 -n 6 \ | 
|  | //      -s 31468618 --language=sv | 
|  | // | 
|  | // Hamming distance histogram: | 
|  | // | 
|  | //  0: -- | 
|  | //  1: -- | 
|  | //  2: -- | 
|  | //  3: |||||||||||||||||||| (57.14%) | 
|  | //  4: ||||||||||||||| (42.86%) | 
|  | //  5: -- | 
|  | //  6: -- | 
|  | // | 
|  | // Minimum Hamming distance: 3 | 
|  | // Maximum Hamming distance: 4 | 
|  | // Minimum Hamming weight: 1 | 
|  | // Maximum Hamming weight: 5 | 
|  | // | 
|  | localparam int CipherCtrlStateWidth = 6; | 
|  | typedef enum logic [CipherCtrlStateWidth-1:0] { | 
|  | CIPHER_CTRL_IDLE        = 6'b001001, | 
|  | CIPHER_CTRL_INIT        = 6'b100011, | 
|  | CIPHER_CTRL_ROUND       = 6'b111101, | 
|  | CIPHER_CTRL_FINISH      = 6'b010000, | 
|  | CIPHER_CTRL_PRNG_RESEED = 6'b100100, | 
|  | CIPHER_CTRL_CLEAR_S     = 6'b111010, | 
|  | CIPHER_CTRL_CLEAR_KD    = 6'b001110, | 
|  | CIPHER_CTRL_ERROR       = 6'b010111 | 
|  | } aes_cipher_ctrl_e; | 
|  |  | 
|  | // $ ./sparse-fsm-encode.py -d 3 -m 3 -n 5 \ | 
|  | //      -s 31468618 --language=sv | 
|  | // | 
|  | // Hamming distance histogram: | 
|  | // | 
|  | //  0: -- | 
|  | //  1: -- | 
|  | //  2: -- | 
|  | //  3: |||||||||||||||||||| (66.67%) | 
|  | //  4: |||||||||| (33.33%) | 
|  | //  5: -- | 
|  | // | 
|  | // Minimum Hamming distance: 3 | 
|  | // Maximum Hamming distance: 4 | 
|  | // | 
|  | localparam int CtrStateWidth = 5; | 
|  | typedef enum logic [CtrStateWidth-1:0] { | 
|  | CTR_IDLE  = 5'b01110, | 
|  | CTR_INCR  = 5'b11000, | 
|  | CTR_ERROR = 5'b00001 | 
|  | } aes_ctr_e; | 
|  |  | 
|  | // Encoding generated with: | 
|  | // $ ./util/design/sparse-fsm-encode.py -d 3 -m 8 -n 6 \ | 
|  | //      -s 31468618 --language=sv | 
|  | // | 
|  | // Hamming distance histogram: | 
|  | // | 
|  | //  0: -- | 
|  | //  1: -- | 
|  | //  2: -- | 
|  | //  3: |||||||||||||||||||| (57.14%) | 
|  | //  4: ||||||||||||||| (42.86%) | 
|  | //  5: -- | 
|  | //  6: -- | 
|  | // | 
|  | // Minimum Hamming distance: 3 | 
|  | // Maximum Hamming distance: 4 | 
|  | // Minimum Hamming weight: 1 | 
|  | // Maximum Hamming weight: 5 | 
|  | // | 
|  | localparam int CtrlStateWidth = 6; | 
|  | typedef enum logic [CtrlStateWidth-1:0] { | 
|  | CTRL_IDLE        = 6'b001001, | 
|  | CTRL_LOAD        = 6'b100011, | 
|  | CTRL_PRNG_UPDATE = 6'b111101, | 
|  | CTRL_PRNG_RESEED = 6'b010000, | 
|  | CTRL_FINISH      = 6'b100100, | 
|  | CTRL_CLEAR_I     = 6'b111010, | 
|  | CTRL_CLEAR_CO    = 6'b001110, | 
|  | CTRL_ERROR       = 6'b010111 | 
|  | } aes_ctrl_e; | 
|  |  | 
|  | // Generic, sparse mux selector encodings | 
|  |  | 
|  | // Encoding generated with: | 
|  | // $ ./util/design/sparse-fsm-encode.py -d 3 -m 2 -n 3 \ | 
|  | //      -s 31468618 --language=sv | 
|  | // | 
|  | // Hamming distance histogram: | 
|  | // | 
|  | //  0: -- | 
|  | //  1: -- | 
|  | //  2: -- | 
|  | //  3: |||||||||||||||||||| (100.00%) | 
|  | // | 
|  | // Minimum Hamming distance: 3 | 
|  | // Maximum Hamming distance: 3 | 
|  | // Minimum Hamming weight: 1 | 
|  | // Maximum Hamming weight: 2 | 
|  | // | 
|  | parameter int Mux2SelWidth = 3; | 
|  | typedef enum logic [Mux2SelWidth-1:0] { | 
|  | MUX2_SEL_0 = 3'b011, | 
|  | MUX2_SEL_1 = 3'b100 | 
|  | } mux2_sel_e; | 
|  |  | 
|  | // Encoding generated with: | 
|  | // $ ./sparse-fsm-encode.py -d 3 -m 3 -n 5 \ | 
|  | //      -s 31468618 --language=sv | 
|  | // | 
|  | // Hamming distance histogram: | 
|  | // | 
|  | //  0: -- | 
|  | //  1: -- | 
|  | //  2: -- | 
|  | //  3: |||||||||||||||||||| (66.67%) | 
|  | //  4: |||||||||| (33.33%) | 
|  | //  5: -- | 
|  | // | 
|  | // Minimum Hamming distance: 3 | 
|  | // Maximum Hamming distance: 4 | 
|  | // | 
|  | parameter int Mux3SelWidth = 5; | 
|  | typedef enum logic [Mux3SelWidth-1:0] { | 
|  | MUX3_SEL_0 = 5'b01110, | 
|  | MUX3_SEL_1 = 5'b11000, | 
|  | MUX3_SEL_2 = 5'b00001 | 
|  | } mux3_sel_e; | 
|  |  | 
|  | // Encoding generated with: | 
|  | // $ ./sparse-fsm-encode.py -d 3 -m 4 -n 5 \ | 
|  | //      -s 31468618 --language=sv | 
|  | // | 
|  | // Hamming distance histogram: | 
|  | // | 
|  | //  0: -- | 
|  | //  1: -- | 
|  | //  2: -- | 
|  | //  3: |||||||||||||||||||| (66.67%) | 
|  | //  4: |||||||||| (33.33%) | 
|  | //  5: -- | 
|  | // | 
|  | // Minimum Hamming distance: 3 | 
|  | // Maximum Hamming distance: 4 | 
|  | // | 
|  | parameter int Mux4SelWidth = 5; | 
|  | typedef enum logic [Mux4SelWidth-1:0] { | 
|  | MUX4_SEL_0 = 5'b01110, | 
|  | MUX4_SEL_1 = 5'b11000, | 
|  | MUX4_SEL_2 = 5'b00001, | 
|  | MUX4_SEL_3 = 5'b10111 | 
|  | } mux4_sel_e; | 
|  |  | 
|  | // $ ./sparse-fsm-encode.py -d 3 -m 6 -n 6 \ | 
|  | //      -s 31468618 --language=sv | 
|  | // | 
|  | // Hamming distance histogram: | 
|  | // | 
|  | //  0: -- | 
|  | //  1: -- | 
|  | //  2: -- | 
|  | //  3: |||||||||||||||||||| (53.33%) | 
|  | //  4: ||||||||||||||| (40.00%) | 
|  | //  5: || (6.67%) | 
|  | //  6: -- | 
|  | // | 
|  | // Minimum Hamming distance: 3 | 
|  | // Maximum Hamming distance: 5 | 
|  | // | 
|  | parameter int Mux6SelWidth = 6; | 
|  | typedef enum logic [Mux6SelWidth-1:0] { | 
|  | MUX6_SEL_0 = 6'b011101, | 
|  | MUX6_SEL_1 = 6'b110000, | 
|  | MUX6_SEL_2 = 6'b001000, | 
|  | MUX6_SEL_3 = 6'b000011, | 
|  | MUX6_SEL_4 = 6'b111110, | 
|  | MUX6_SEL_5 = 6'b100101 | 
|  | } mux6_sel_e; | 
|  |  | 
|  | // Mux selector signal types. These use the generic types defined above. | 
|  |  | 
|  | parameter int DIPSelNum = 2; | 
|  | parameter int DIPSelWidth = Mux2SelWidth; | 
|  | typedef enum logic [DIPSelWidth-1:0] { | 
|  | DIP_DATA_IN = MUX2_SEL_0, | 
|  | DIP_CLEAR   = MUX2_SEL_1 | 
|  | } dip_sel_e; | 
|  |  | 
|  | parameter int SISelNum = 2; | 
|  | parameter int SISelWidth = Mux2SelWidth; | 
|  | typedef enum logic [SISelWidth-1:0] { | 
|  | SI_ZERO = MUX2_SEL_0, | 
|  | SI_DATA = MUX2_SEL_1 | 
|  | } si_sel_e; | 
|  |  | 
|  | parameter int AddSISelNum = 2; | 
|  | parameter int AddSISelWidth = Mux2SelWidth; | 
|  | typedef enum logic [AddSISelWidth-1:0] { | 
|  | ADD_SI_ZERO = MUX2_SEL_0, | 
|  | ADD_SI_IV   = MUX2_SEL_1 | 
|  | } add_si_sel_e; | 
|  |  | 
|  | parameter int StateSelNum = 3; | 
|  | parameter int StateSelWidth = Mux3SelWidth; | 
|  | typedef enum logic [StateSelWidth-1:0] { | 
|  | STATE_INIT  = MUX3_SEL_0, | 
|  | STATE_ROUND = MUX3_SEL_1, | 
|  | STATE_CLEAR = MUX3_SEL_2 | 
|  | } state_sel_e; | 
|  |  | 
|  | parameter int AddRKSelNum = 3; | 
|  | parameter int AddRKSelWidth = Mux3SelWidth; | 
|  | typedef enum logic [AddRKSelWidth-1:0] { | 
|  | ADD_RK_INIT  = MUX3_SEL_0, | 
|  | ADD_RK_ROUND = MUX3_SEL_1, | 
|  | ADD_RK_FINAL = MUX3_SEL_2 | 
|  | } add_rk_sel_e; | 
|  |  | 
|  | parameter int KeyInitSelNum = 3; | 
|  | parameter int KeyInitSelWidth = Mux3SelWidth; | 
|  | typedef enum logic [KeyInitSelWidth-1:0] { | 
|  | KEY_INIT_INPUT  = MUX3_SEL_0, | 
|  | KEY_INIT_KEYMGR = MUX3_SEL_1, | 
|  | KEY_INIT_CLEAR  = MUX3_SEL_2 | 
|  | } key_init_sel_e; | 
|  |  | 
|  | parameter int IVSelNum = 6; | 
|  | parameter int IVSelWidth = Mux6SelWidth; | 
|  | typedef enum logic [IVSelWidth-1:0] { | 
|  | IV_INPUT        = MUX6_SEL_0, | 
|  | IV_DATA_OUT     = MUX6_SEL_1, | 
|  | IV_DATA_OUT_RAW = MUX6_SEL_2, | 
|  | IV_DATA_IN_PREV = MUX6_SEL_3, | 
|  | IV_CTR          = MUX6_SEL_4, | 
|  | IV_CLEAR        = MUX6_SEL_5 | 
|  | } iv_sel_e; | 
|  |  | 
|  | parameter int KeyFullSelNum = 4; | 
|  | parameter int KeyFullSelWidth = Mux4SelWidth; | 
|  | typedef enum logic [KeyFullSelWidth-1:0] { | 
|  | KEY_FULL_ENC_INIT = MUX4_SEL_0, | 
|  | KEY_FULL_DEC_INIT = MUX4_SEL_1, | 
|  | KEY_FULL_ROUND    = MUX4_SEL_2, | 
|  | KEY_FULL_CLEAR    = MUX4_SEL_3 | 
|  | } key_full_sel_e; | 
|  |  | 
|  | parameter int KeyDecSelNum = 2; | 
|  | parameter int KeyDecSelWidth = Mux2SelWidth; | 
|  | typedef enum logic [KeyDecSelWidth-1:0] { | 
|  | KEY_DEC_EXPAND = MUX2_SEL_0, | 
|  | KEY_DEC_CLEAR  = MUX2_SEL_1 | 
|  | } key_dec_sel_e; | 
|  |  | 
|  | parameter int KeyWordsSelNum = 4; | 
|  | parameter int KeyWordsSelWidth = Mux4SelWidth; | 
|  | typedef enum logic [KeyWordsSelWidth-1:0] { | 
|  | KEY_WORDS_0123 = MUX4_SEL_0, | 
|  | KEY_WORDS_2345 = MUX4_SEL_1, | 
|  | KEY_WORDS_4567 = MUX4_SEL_2, | 
|  | KEY_WORDS_ZERO = MUX4_SEL_3 | 
|  | } key_words_sel_e; | 
|  |  | 
|  | parameter int RoundKeySelNum = 2; | 
|  | parameter int RoundKeySelWidth = Mux2SelWidth; | 
|  | typedef enum logic [RoundKeySelWidth-1:0] { | 
|  | ROUND_KEY_DIRECT = MUX2_SEL_0, | 
|  | ROUND_KEY_MIXED  = MUX2_SEL_1 | 
|  | } round_key_sel_e; | 
|  |  | 
|  | parameter int AddSOSelNum = 3; | 
|  | parameter int AddSOSelWidth = Mux3SelWidth; | 
|  | typedef enum logic [AddSOSelWidth-1:0] { | 
|  | ADD_SO_ZERO = MUX3_SEL_0, | 
|  | ADD_SO_IV   = MUX3_SEL_1, | 
|  | ADD_SO_DIP  = MUX3_SEL_2 | 
|  | } add_so_sel_e; | 
|  |  | 
|  | // Sparse two-value signal type sp2v_e | 
|  | parameter int Sp2VNum = 2; | 
|  | parameter int Sp2VWidth = Mux2SelWidth; | 
|  | typedef enum logic [Sp2VWidth-1:0] { | 
|  | SP2V_HIGH = MUX2_SEL_0, | 
|  | SP2V_LOW  = MUX2_SEL_1 | 
|  | } sp2v_e; | 
|  |  | 
|  | typedef logic [Sp2VWidth-1:0] sp2v_logic_t; | 
|  | parameter sp2v_logic_t SP2V_LOGIC_HIGH = {SP2V_HIGH}; | 
|  |  | 
|  | // Control register type | 
|  | typedef struct packed { | 
|  | logic      manual_operation; | 
|  | prs_rate_e prng_reseed_rate; | 
|  | logic      sideload; | 
|  | key_len_e  key_len; | 
|  | aes_mode_e mode; | 
|  | aes_op_e   operation; | 
|  | } ctrl_reg_t; | 
|  |  | 
|  | parameter ctrl_reg_t CTRL_RESET = '{ | 
|  | manual_operation: aes_reg_pkg::AES_CTRL_SHADOWED_MANUAL_OPERATION_RESVAL, | 
|  | prng_reseed_rate: prs_rate_e'(aes_reg_pkg::AES_CTRL_SHADOWED_PRNG_RESEED_RATE_RESVAL), | 
|  | sideload:         aes_reg_pkg::AES_CTRL_SHADOWED_SIDELOAD_RESVAL, | 
|  | key_len:          key_len_e'(aes_reg_pkg::AES_CTRL_SHADOWED_KEY_LEN_RESVAL), | 
|  | mode:             aes_mode_e'(aes_reg_pkg::AES_CTRL_SHADOWED_MODE_RESVAL), | 
|  | operation:        aes_op_e'(aes_reg_pkg::AES_CTRL_SHADOWED_OPERATION_RESVAL) | 
|  | }; | 
|  |  | 
|  | // Multiplication by {02} (i.e. x) on GF(2^8) | 
|  | // with field generating polynomial {01}{1b} (9'h11b) | 
|  | // Sometimes also denoted by xtime(). | 
|  | function automatic logic [7:0] aes_mul2(logic [7:0] in); | 
|  | logic [7:0] out; | 
|  | out[7] = in[6]; | 
|  | out[6] = in[5]; | 
|  | out[5] = in[4]; | 
|  | out[4] = in[3] ^ in[7]; | 
|  | out[3] = in[2] ^ in[7]; | 
|  | out[2] = in[1]; | 
|  | out[1] = in[0] ^ in[7]; | 
|  | out[0] = in[7]; | 
|  | return out; | 
|  | endfunction | 
|  |  | 
|  | // Multiplication by {04} (i.e. x^2) on GF(2^8) | 
|  | // with field generating polynomial {01}{1b} (9'h11b) | 
|  | function automatic logic [7:0] aes_mul4(logic [7:0] in); | 
|  | return aes_mul2(aes_mul2(in)); | 
|  | endfunction | 
|  |  | 
|  | // Division by {02} (i.e. x) on GF(2^8) | 
|  | // with field generating polynomial {01}{1b} (9'h11b) | 
|  | // This is the inverse of aes_mul2() or xtime(). | 
|  | function automatic logic [7:0] aes_div2(logic [7:0] in); | 
|  | logic [7:0] out; | 
|  | out[7] = in[0]; | 
|  | out[6] = in[7]; | 
|  | out[5] = in[6]; | 
|  | out[4] = in[5]; | 
|  | out[3] = in[4] ^ in[0]; | 
|  | out[2] = in[3] ^ in[0]; | 
|  | out[1] = in[2]; | 
|  | out[0] = in[1] ^ in[0]; | 
|  | return out; | 
|  | endfunction | 
|  |  | 
|  | // Circular byte shift to the left | 
|  | function automatic logic [31:0] aes_circ_byte_shift(logic [31:0] in, logic [1:0] shift); | 
|  | logic [31:0] out; | 
|  | logic [31:0] s; | 
|  | s = {30'b0,shift}; | 
|  | out = {in[8*((7-s)%4) +: 8], in[8*((6-s)%4) +: 8], | 
|  | in[8*((5-s)%4) +: 8], in[8*((4-s)%4) +: 8]}; | 
|  | return out; | 
|  | endfunction | 
|  |  | 
|  | // Transpose state matrix | 
|  | function automatic logic [3:0][3:0][7:0] aes_transpose(logic [3:0][3:0][7:0] in); | 
|  | logic [3:0][3:0][7:0] transpose; | 
|  | transpose = '0; | 
|  | for (int j = 0; j < 4; j++) begin | 
|  | for (int i = 0; i < 4; i++) begin | 
|  | transpose[i][j] = in[j][i]; | 
|  | end | 
|  | end | 
|  | return transpose; | 
|  | endfunction | 
|  |  | 
|  | // Extract single column from state matrix | 
|  | function automatic logic [3:0][7:0] aes_col_get(logic [3:0][3:0][7:0] in, logic [1:0] idx); | 
|  | logic [3:0][7:0] out; | 
|  | for (int i = 0; i < 4; i++) begin | 
|  | out[i] = in[i][idx]; | 
|  | end | 
|  | return out; | 
|  | endfunction | 
|  |  | 
|  | // Matrix-vector multiplication in GF(2^8): c = A * b | 
|  | function automatic logic [7:0] aes_mvm( | 
|  | logic [7:0] vec_b, | 
|  | logic [7:0] mat_a [8] | 
|  | ); | 
|  | logic [7:0] vec_c; | 
|  | vec_c = '0; | 
|  | for (int i = 0; i < 8; i++) begin | 
|  | for (int j = 0; j < 8; j++) begin | 
|  | vec_c[i] = vec_c[i] ^ (mat_a[j][i] & vec_b[7-j]); | 
|  | end | 
|  | end | 
|  | return vec_c; | 
|  | endfunction | 
|  |  | 
|  | // Rotate integer indices | 
|  | function automatic integer aes_rot_int(integer in, integer num); | 
|  | integer out; | 
|  | if (in == 0) begin | 
|  | out = num - 1; | 
|  | end else begin | 
|  | out = in - 1; | 
|  | end | 
|  | return out; | 
|  | endfunction | 
|  |  | 
|  | // Function for extracting LSBs of the per-S-Box pseudo-random data (PRD) from the output of the | 
|  | // masking PRNG. | 
|  | // | 
|  | // The masking PRNG is used for generating both the PRD for the S-Boxes/SubBytes operation as | 
|  | // well as for the input data masks. When using any of the masked Canright S-Box implementations, | 
|  | // it is important that the SubBytes input masks (generated by the PRNG in Round X-1) and the | 
|  | // SubBytes output masks (generated by the PRNG in Round X) are independent. Inside the PRNG, | 
|  | // this is achieved by using multiple, separately re-seeded LFSR chunks and by selecting the | 
|  | // separate LFSR chunks in alternating fashion. Since the input data masks become the SubBytes | 
|  | // input masks in the first round, we select the same 8 bit lanes for the input data masks which | 
|  | // are also used to form the SubBytes output mask for the masked Canright S-Box implementations, | 
|  | // i.e., the 8 LSBs of the per S-Box PRD. In particular, we have: | 
|  | // | 
|  | // prng_output = { prd_key_expand, ... , sb_prd[4], sb_out_mask[4], sb_prd[0], sb_out_mask[0] } | 
|  | // | 
|  | // Where sb_out_mask[x] contains the SubBytes output mask for byte x (when using a masked | 
|  | // Canright S-Box implementation) and sb_prd[x] contains additional PRD consumed by SubBytes for | 
|  | // byte x. | 
|  | // | 
|  | // When using a masked S-Box implementation other than Canright, we still select the 8 LSBs of | 
|  | // the per-S-Box PRD to form the input data mask of the corresponding byte. We do this to | 
|  | // distribute the input data masks over all LFSR chunks of the masking PRNG. | 
|  |  | 
|  | // For one row of the state matrix, extract the 8 LSBs of the per-S-Box PRD from the PRNG output. | 
|  | // These bits are used as: | 
|  | // - input data masks, and | 
|  | // - SubBytes output mask when using a masked Canright S-Box implementation. | 
|  | function automatic logic [3:0][7:0] aes_prd_get_lsbs( | 
|  | logic [(4*WidthPRDSBox)-1:0] in | 
|  | ); | 
|  | logic [3:0][7:0] prd_lsbs; | 
|  | for (int i = 0; i < 4; i++) begin | 
|  | prd_lsbs[i] = in[i*WidthPRDSBox +: 8]; | 
|  | end | 
|  | return prd_lsbs; | 
|  | endfunction | 
|  |  | 
|  | endpackage |