../src/lowrisc_ip_aes_0.6/rtl/aes_sbox_canright_masked_noreuse.sv Cov: 100%

   1: // Copyright lowRISC contributors.
   2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   3: // SPDX-License-Identifier: Apache-2.0
   4: //
   5: // AES Masked Canright SBox without Mask Re-Use
   6: //
   7: // For details, see the following paper:
   8: // Canright, "A very compact 'perfectly masked' S-box for AES (corrected)"
   9: // available at https://eprint.iacr.org/2009/011.pdf
  10: //
  11: // Note: This module implements the original masked inversion algorithm without re-using masks.
  12: // For details, see Section 2.2 of the paper.
  13: 
  14: ///////////////////////////////////////////////////////////////////////////////////////////////////
  15: // IMPORTANT NOTE:                                                                               //
  16: //                            DO NOT USE THIS FOR SYNTHESIS BLINDLY!                             //
  17: //                                                                                               //
  18: // This is a high-level implementation targeting primarily RTL simulation. Synthesis tools might //
  19: // heavily optimize the design. The result is likely insecure. Use with care.                    //
  20: ///////////////////////////////////////////////////////////////////////////////////////////////////
  21: 
  22: module aes_sbox_canright_masked_noreuse (
  23:   input  aes_pkg::ciph_op_e op_i,
  24:   input  logic [7:0]        data_i,     // masked, the actual input data is data_i ^ in_mask_i
  25:   input  logic [7:0]        in_mask_i,  // input mask, independent from actual input data
  26:   input  logic [7:0]        out_mask_i, // output mask, independent from input mask
  27:   output logic [7:0]        data_o      // masked, the actual output data is data_o ^ out_mask_i
  28: );
  29: 
  30:   import aes_pkg::*;
  31:   import aes_sbox_canright_pkg::*;
  32: 
  33:   ///////////////
  34:   // Functions //
  35:   ///////////////
  36: 
  37:   // Masked inverse in GF(2^4), using normal basis [z^4, z]
  38:   // (see Formulas 6, 13, 14, 15, 16, 17 in the paper)
  39:   function automatic logic [3:0] aes_masked_inverse_gf2p4(logic [3:0] b,
  40:                                                           logic [3:0] q,
  41:                                                           logic [1:0] r,
  42:                                                           logic [3:0] t);
  43:     logic [3:0] b_inv;
  44:     logic [1:0] b1, b0, q1, q0, c, c_inv, r_sq, t1, t0, b1_inv, b0_inv;
  45:     b1 = b[3:2];
  46:     b0 = b[1:0];
  47:     q1 = q[3:2];
  48:     q0 = q[1:0];
  49:     t1 = t[3:2];
  50:     t0 = t[1:0];
  51: 
  52:     // Formula 13
  53:     // IMPORTANT: The following ops must be executed in order (left to right):
  54:     c = r ^ aes_scale_omega2_gf2p2(aes_square_gf2p2(b1 ^ b0))
  55:           ^ aes_scale_omega2_gf2p2(aes_square_gf2p2(q1 ^ q0))
  56:           ^ aes_mul_gf2p2(b1, b0)
  57:           ^ aes_mul_gf2p2(b1, q0) ^ aes_mul_gf2p2(b0, q1) ^ aes_mul_gf2p2(q1, q0);
  58:     //
  59: 
  60:     // Formulas 14 and 15
  61:     c_inv = aes_square_gf2p2(c);
  62:     r_sq  = aes_square_gf2p2(r);
  63: 
  64:     // Formulas 16 and 17
  65:     // IMPORTANT: The following ops must be executed in order (left to right):
  66:     b1_inv = t1 ^ aes_mul_gf2p2(b0, c_inv)
  67:                 ^ aes_mul_gf2p2(b0, r_sq) ^ aes_mul_gf2p2(q0, c_inv) ^ aes_mul_gf2p2(q0, r_sq);
  68:     b0_inv = t0 ^ aes_mul_gf2p2(b1, c_inv)
  69:                 ^ aes_mul_gf2p2(b1, r_sq) ^ aes_mul_gf2p2(q1, c_inv) ^ aes_mul_gf2p2(q1, r_sq);
  70:     //
  71: 
  72:     // Note: b_inv is masked by t, b was masked by q.
  73:     b_inv = {b1_inv, b0_inv};
  74: 
  75:     return b_inv;
  76:   endfunction
  77: 
  78:   // Masked inverse in GF(2^8), using normal basis [y^16, y]
  79:   // (see Formulas 3, 12, 18 and 19 in the paper)
  80:   function automatic logic [7:0] aes_masked_inverse_gf2p8(logic [7:0] a,
  81:                                                           logic [7:0] m,
  82:                                                           logic [7:0] n);
  83:     logic [7:0] a_inv;
  84:     logic [3:0] a1, a0, m1, m0, b, b_inv, q, s1, s0, t, a1_inv, a0_inv;
  85:     logic [1:0] r;
  86:     a1 = a[7:4];
  87:     a0 = a[3:0];
  88:     m1 = m[7:4];
  89:     m0 = m[3:0];
  90: 
  91:     // q must be independent of m.
  92:     q = n[7:4];
  93: 
  94:     // Formula 12
  95:     // IMPORTANT: The following ops must be executed in order (left to right):
  96:     b = q ^ aes_square_scale_gf2p4_gf2p2(a1 ^ a0)
  97:           ^ aes_square_scale_gf2p4_gf2p2(m1 ^ m0)
  98:           ^ aes_mul_gf2p4(a1, a0)
  99:           ^ aes_mul_gf2p4(a1, m0) ^ aes_mul_gf2p4(a0, m1) ^ aes_mul_gf2p4(m1, m0);
 100:     //
 101: 
 102:     // r must be independent of q.
 103:     r = m1[3:2];
 104: 
 105:     // Note that the paper states the following requirements on t:
 106:     // - t must be independent of r.
 107:     // - t1 must be independent of q0, t0 must be independent of q1.
 108:     // - t must be independent of m (for the final steps involving s)
 109:     // The paper suggests to use t = q. To select s = n for the output mask (s must be independent
 110:     // of t = q = n[7:4]), we would need t = m0 or similar (not r, m1[3:2] though), but this would
 111:     // break the random product distribution of aes_mul_gf2p4(m0, t), or aes_mul_gf2p4(m1, t) below
 112:     // (see Lemma 2 in the paper). For this reason, we select t = q here and apply a final mask
 113:     // switch from s = m to n after the inversion.
 114:     t = q;
 115: 
 116:     // b is masked by q, b_inv is masked by t.
 117:     b_inv = aes_masked_inverse_gf2p4(b, q, r, t);
 118: 
 119:     // Note that the paper states the following requirements on s:
 120:     // - s must be independent of t
 121:     // - s1 must be independent of m0, s0 must be independent of m1.
 122:     // The paper suggests to use s = m (the input mask). To still end up with the specified output
 123:     // mask n, we will apply a final mask switch after the inversion.
 124:     s1 = m1;
 125:     s0 = m0;
 126: 
 127:     // Formulas 18 and 19
 128:     // IMPORTANT: The following ops must be executed in order (left to right):
 129:     a1_inv = s1 ^ aes_mul_gf2p4(a0, b_inv)
 130:                 ^ aes_mul_gf2p4(a0, t) ^ aes_mul_gf2p4(m0, b_inv) ^ aes_mul_gf2p4(m0, t);
 131:     a0_inv = s0 ^ aes_mul_gf2p4(a1, b_inv)
 132:                 ^ aes_mul_gf2p4(a1, t) ^ aes_mul_gf2p4(m1, b_inv) ^ aes_mul_gf2p4(m1, t);
 133:     //
 134: 
 135:     // Note: a_inv is now masked by s = m, a was masked by m.
 136:     a_inv = {a1_inv, a0_inv};
 137: 
 138:     // To have a_inv masked by n (the specified output mask), we perform a final mask switch.
 139:     // IMPORTANT: The following ops must be executed in order (left to right):
 140:     a_inv = a_inv ^ n ^ m;
 141:     //
 142: 
 143:     return a_inv;
 144:   endfunction
 145: 
 146:   //////////////////////////
 147:   // Masked Canright SBox //
 148:   //////////////////////////
 149: 
 150:   logic [7:0] data_basis_x, data_inverse;
 151:   logic [7:0] in_mask_basis_x;
 152:   logic [7:0] out_mask_basis_x;
 153: 
 154:   // Convert data to normal basis X.
 155:   assign data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) :
 156:                                              aes_mvm(data_i ^ 8'h63, S2X);
 157: 
 158:   // Convert masks to normal basis X.
 159:   // The addition of constant 8'h63 following the affine transformation is skipped.
 160:   assign in_mask_basis_x  = (op_i == CIPH_FWD) ? aes_mvm(in_mask_i, A2X) :
 161:                                                  aes_mvm(in_mask_i, S2X);
 162: 
 163:   // The output mask is converted in the opposite direction.
 164:   assign out_mask_basis_x = (op_i == CIPH_INV) ? aes_mvm(out_mask_i, A2X) :
 165:                                                  aes_mvm(out_mask_i, S2X);
 166: 
 167:   // Do the inversion in normal basis X.
 168:   assign data_inverse = aes_masked_inverse_gf2p8(data_basis_x, in_mask_basis_x, out_mask_basis_x);
 169: 
 170:   // Convert to basis S or A.
 171:   assign data_o = (op_i == CIPH_FWD) ? (aes_mvm(data_inverse, X2S) ^ 8'h63) :
 172:                                        (aes_mvm(data_inverse, X2A));
 173: 
 174: endmodule
 175: