../src/lowrisc_prim_all_0.1/rtl/prim_cipher_pkg.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: // This package holds common constants and functions for PRESENT- and
   6: // PRINCE-based scrambling devices.
   7: //
   8: // See also: prim_present, prim_prince
   9: //
  10: // References: - https://en.wikipedia.org/wiki/PRESENT
  11: //             - https://en.wikipedia.org/wiki/Prince_(cipher)
  12: //             - http://www.lightweightcrypto.org/present/present_ches2007.pdf
  13: //             - https://eprint.iacr.org/2012/529.pdf
  14: //             - https://eprint.iacr.org/2015/372.pdf
  15: //             - https://eprint.iacr.org/2014/656.pdf
  16: 
  17: package prim_cipher_pkg;
  18: 
  19:   ///////////////////
  20:   // PRINCE Cipher //
  21:   ///////////////////
  22: 
  23:   parameter logic [15:0][3:0] PRINCE_SBOX4 = {4'h4, 4'hD, 4'h5, 4'hE,
  24:                                               4'h0, 4'h8, 4'h7, 4'h6,
  25:                                               4'h1, 4'h9, 4'hC, 4'hA,
  26:                                               4'h2, 4'h3, 4'hF, 4'hB};
  27: 
  28:   parameter logic [15:0][3:0] PRINCE_SBOX4_INV = {4'h1, 4'hC, 4'hE, 4'h5,
  29:                                                   4'h0, 4'h4, 4'h6, 4'hA,
  30:                                                   4'h9, 4'h8, 4'hD, 4'hF,
  31:                                                   4'h2, 4'h3, 4'h7, 4'hB};
  32:   // nibble permutations
  33:   parameter logic [15:0][3:0] PRINCE_SHIFT_ROWS64  = '{4'hB, 4'h6, 4'h1, 4'hC,
  34:                                                        4'h7, 4'h2, 4'hD, 4'h8,
  35:                                                        4'h3, 4'hE, 4'h9, 4'h4,
  36:                                                        4'hF, 4'hA, 4'h5, 4'h0};
  37: 
  38:   parameter logic [15:0][3:0] PRINCE_SHIFT_ROWS64_INV = '{4'h3, 4'h6, 4'h9, 4'hC,
  39:                                                           4'hF, 4'h2, 4'h5, 4'h8,
  40:                                                           4'hB, 4'hE, 4'h1, 4'h4,
  41:                                                           4'h7, 4'hA, 4'hD, 4'h0};
  42: 
  43:   // these are the round constants
  44:   parameter logic [11:0][63:0] PRINCE_ROUND_CONST = {64'hC0AC29B7C97C50DD,
  45:                                                      64'hD3B5A399CA0C2399,
  46:                                                      64'h64A51195E0E3610D,
  47:                                                      64'hC882D32F25323C54,
  48:                                                      64'h85840851F1AC43AA,
  49:                                                      64'h7EF84F78FD955CB1,
  50:                                                      64'hBE5466CF34E90C6C,
  51:                                                      64'h452821E638D01377,
  52:                                                      64'h082EFA98EC4E6C89,
  53:                                                      64'hA4093822299F31D0,
  54:                                                      64'h13198A2E03707344,
  55:                                                      64'h0000000000000000};
  56: 
  57:   // tweak constant for key modification between enc/dec modes
  58:   parameter logic [63:0] PRINCE_ALPHA_CONST = 64'hC0AC29B7C97C50DD;
  59: 
  60:   // masking constants for shift rows function below
  61:   parameter logic [15:0] PRINCE_SHIFT_ROWS_CONST0 = 16'hEDB7;
  62:   parameter logic [15:0] PRINCE_SHIFT_ROWS_CONST1 = 16'h7EDB;
  63:   parameter logic [15:0] PRINCE_SHIFT_ROWS_CONST2 = 16'hB7ED;
  64:   parameter logic [15:0] PRINCE_SHIFT_ROWS_CONST3 = 16'hDB7E;
  65: 
  66:   // nibble shifts
  67:   function automatic logic [31:0] prince_shiftrows_32bit(logic [31:0]      state_in,
  68:                                                          logic [15:0][3:0] shifts );
  69:     logic [31:0] state_out;
  70:     // note that if simulation performance becomes an issue, this loop can be unrolled
  71:     for (int k = 0; k < 32/2; k++) begin
  72:       // operate on pairs of 2bit instead of nibbles
  73:       state_out[k*2  +: 2] = state_in[shifts[k]*2  +: 2];
  74:     end
  75:     return state_out;
  76:   endfunction : prince_shiftrows_32bit
  77: 
  78:   function automatic logic [63:0] prince_shiftrows_64bit(logic [63:0]      state_in,
  79:                                                          logic [15:0][3:0] shifts );
  80:     logic [63:0] state_out;
  81:     // note that if simulation performance becomes an issue, this loop can be unrolled
  82:     for (int k = 0; k < 64/4; k++) begin
  83:       state_out[k*4  +: 4] = state_in[shifts[k]*4  +: 4];
  84:     end
  85:     return state_out;
  86:   endfunction : prince_shiftrows_64bit
  87: 
  88:   // XOR reduction of four nibbles in a 16bit subvector
  89:   function automatic logic [3:0] prince_nibble_red16(logic [15:0] vect);
  90:     return vect[0 +: 4] ^ vect[4 +: 4] ^ vect[8 +: 4] ^ vect[12 +: 4];
  91:   endfunction : prince_nibble_red16
  92: 
  93:   // M prime multiplication
  94:   function automatic logic [31:0] prince_mult_prime_32bit(logic [31:0] state_in);
  95:     logic [31:0] state_out;
  96:     // M0
  97:     state_out[0  +: 4] = prince_nibble_red16(state_in[ 0 +: 16] & PRINCE_SHIFT_ROWS_CONST0);
  98:     state_out[4  +: 4] = prince_nibble_red16(state_in[ 0 +: 16] & PRINCE_SHIFT_ROWS_CONST1);
  99:     state_out[8  +: 4] = prince_nibble_red16(state_in[ 0 +: 16] & PRINCE_SHIFT_ROWS_CONST2);
 100:     state_out[12 +: 4] = prince_nibble_red16(state_in[ 0 +: 16] & PRINCE_SHIFT_ROWS_CONST3);
 101:     // M1
 102:     state_out[16 +: 4] = prince_nibble_red16(state_in[16 +: 16] & PRINCE_SHIFT_ROWS_CONST1);
 103:     state_out[20 +: 4] = prince_nibble_red16(state_in[16 +: 16] & PRINCE_SHIFT_ROWS_CONST2);
 104:     state_out[24 +: 4] = prince_nibble_red16(state_in[16 +: 16] & PRINCE_SHIFT_ROWS_CONST3);
 105:     state_out[28 +: 4] = prince_nibble_red16(state_in[16 +: 16] & PRINCE_SHIFT_ROWS_CONST0);
 106:     return state_out;
 107:   endfunction : prince_mult_prime_32bit
 108: 
 109:   // M prime multiplication
 110:   function automatic logic [63:0] prince_mult_prime_64bit(logic [63:0] state_in);
 111:     logic [63:0] state_out;
 112:     // M0
 113:     state_out[0  +: 4] = prince_nibble_red16(state_in[ 0 +: 16] & PRINCE_SHIFT_ROWS_CONST0);
 114:     state_out[4  +: 4] = prince_nibble_red16(state_in[ 0 +: 16] & PRINCE_SHIFT_ROWS_CONST1);
 115:     state_out[8  +: 4] = prince_nibble_red16(state_in[ 0 +: 16] & PRINCE_SHIFT_ROWS_CONST2);
 116:     state_out[12 +: 4] = prince_nibble_red16(state_in[ 0 +: 16] & PRINCE_SHIFT_ROWS_CONST3);
 117:     // M1
 118:     state_out[16 +: 4] = prince_nibble_red16(state_in[16 +: 16] & PRINCE_SHIFT_ROWS_CONST1);
 119:     state_out[20 +: 4] = prince_nibble_red16(state_in[16 +: 16] & PRINCE_SHIFT_ROWS_CONST2);
 120:     state_out[24 +: 4] = prince_nibble_red16(state_in[16 +: 16] & PRINCE_SHIFT_ROWS_CONST3);
 121:     state_out[28 +: 4] = prince_nibble_red16(state_in[16 +: 16] & PRINCE_SHIFT_ROWS_CONST0);
 122:     // M1
 123:     state_out[32 +: 4] = prince_nibble_red16(state_in[32 +: 16] & PRINCE_SHIFT_ROWS_CONST1);
 124:     state_out[36 +: 4] = prince_nibble_red16(state_in[32 +: 16] & PRINCE_SHIFT_ROWS_CONST2);
 125:     state_out[40 +: 4] = prince_nibble_red16(state_in[32 +: 16] & PRINCE_SHIFT_ROWS_CONST3);
 126:     state_out[44 +: 4] = prince_nibble_red16(state_in[32 +: 16] & PRINCE_SHIFT_ROWS_CONST0);
 127:     // M0
 128:     state_out[48 +: 4] = prince_nibble_red16(state_in[48 +: 16] & PRINCE_SHIFT_ROWS_CONST0);
 129:     state_out[52 +: 4] = prince_nibble_red16(state_in[48 +: 16] & PRINCE_SHIFT_ROWS_CONST1);
 130:     state_out[56 +: 4] = prince_nibble_red16(state_in[48 +: 16] & PRINCE_SHIFT_ROWS_CONST2);
 131:     state_out[60 +: 4] = prince_nibble_red16(state_in[48 +: 16] & PRINCE_SHIFT_ROWS_CONST3);
 132:     return state_out;
 133:   endfunction : prince_mult_prime_64bit
 134: 
 135: 
 136:   ////////////////////
 137:   // PRESENT Cipher //
 138:   ////////////////////
 139: 
 140:   // this is the sbox from the present cipher
 141:   parameter logic [15:0][3:0] PRESENT_SBOX4 = {4'h2, 4'h1, 4'h7, 4'h4,
 142:                                                4'h8, 4'hF, 4'hE, 4'h3,
 143:                                                4'hD, 4'hA, 4'h0, 4'h9,
 144:                                                4'hB, 4'h6, 4'h5, 4'hC};
 145: 
 146:   parameter logic [15:0][3:0] PRESENT_SBOX4_INV = {4'hA, 4'h9, 4'h7, 4'h0,
 147:                                                    4'h3, 4'h6, 4'h4, 4'hB,
 148:                                                    4'hD, 4'h2, 4'h1, 4'hC,
 149:                                                    4'h8, 4'hF, 4'hE, 4'h5};
 150: 
 151:   // these are modified permutation indices for a 32bit version that
 152:   // follow the same pattern as for the 64bit version
 153:   parameter logic [31:0][4:0] PRESENT_PERM32 = {5'd31, 5'd23, 5'd15, 5'd07,
 154:                                                 5'd30, 5'd22, 5'd14, 5'd06,
 155:                                                 5'd29, 5'd21, 5'd13, 5'd05,
 156:                                                 5'd28, 5'd20, 5'd12, 5'd04,
 157:                                                 5'd27, 5'd19, 5'd11, 5'd03,
 158:                                                 5'd26, 5'd18, 5'd10, 5'd02,
 159:                                                 5'd25, 5'd17, 5'd09, 5'd01,
 160:                                                 5'd24, 5'd16, 5'd08, 5'd00};
 161: 
 162:   parameter logic [31:0][4:0] PRESENT_PERM32_INV = {5'd31, 5'd27, 5'd23, 5'd19,
 163:                                                     5'd15, 5'd11, 5'd07, 5'd03,
 164:                                                     5'd30, 5'd26, 5'd22, 5'd18,
 165:                                                     5'd14, 5'd10, 5'd06, 5'd02,
 166:                                                     5'd29, 5'd25, 5'd21, 5'd17,
 167:                                                     5'd13, 5'd09, 5'd05, 5'd01,
 168:                                                     5'd28, 5'd24, 5'd20, 5'd16,
 169:                                                     5'd12, 5'd08, 5'd04, 5'd00};
 170: 
 171:   // these are the permutation indices of the present cipher
 172:   parameter logic [63:0][5:0] PRESENT_PERM64 = {6'd63, 6'd47, 6'd31, 6'd15,
 173:                                                 6'd62, 6'd46, 6'd30, 6'd14,
 174:                                                 6'd61, 6'd45, 6'd29, 6'd13,
 175:                                                 6'd60, 6'd44, 6'd28, 6'd12,
 176:                                                 6'd59, 6'd43, 6'd27, 6'd11,
 177:                                                 6'd58, 6'd42, 6'd26, 6'd10,
 178:                                                 6'd57, 6'd41, 6'd25, 6'd09,
 179:                                                 6'd56, 6'd40, 6'd24, 6'd08,
 180:                                                 6'd55, 6'd39, 6'd23, 6'd07,
 181:                                                 6'd54, 6'd38, 6'd22, 6'd06,
 182:                                                 6'd53, 6'd37, 6'd21, 6'd05,
 183:                                                 6'd52, 6'd36, 6'd20, 6'd04,
 184:                                                 6'd51, 6'd35, 6'd19, 6'd03,
 185:                                                 6'd50, 6'd34, 6'd18, 6'd02,
 186:                                                 6'd49, 6'd33, 6'd17, 6'd01,
 187:                                                 6'd48, 6'd32, 6'd16, 6'd00};
 188: 
 189:   parameter logic [63:0][5:0] PRESENT_PERM64_INV = {6'd63, 6'd59, 6'd55, 6'd51,
 190:                                                     6'd47, 6'd43, 6'd39, 6'd35,
 191:                                                     6'd31, 6'd27, 6'd23, 6'd19,
 192:                                                     6'd15, 6'd11, 6'd07, 6'd03,
 193:                                                     6'd62, 6'd58, 6'd54, 6'd50,
 194:                                                     6'd46, 6'd42, 6'd38, 6'd34,
 195:                                                     6'd30, 6'd26, 6'd22, 6'd18,
 196:                                                     6'd14, 6'd10, 6'd06, 6'd02,
 197:                                                     6'd61, 6'd57, 6'd53, 6'd49,
 198:                                                     6'd45, 6'd41, 6'd37, 6'd33,
 199:                                                     6'd29, 6'd25, 6'd21, 6'd17,
 200:                                                     6'd13, 6'd09, 6'd05, 6'd01,
 201:                                                     6'd60, 6'd56, 6'd52, 6'd48,
 202:                                                     6'd44, 6'd40, 6'd36, 6'd32,
 203:                                                     6'd28, 6'd24, 6'd20, 6'd16,
 204:                                                     6'd12, 6'd08, 6'd04, 6'd00};
 205: 
 206:   // forward key schedule
 207:   function automatic logic [63:0] present_update_key64(logic [63:0] key_in,
 208:                                                        logic [4:0]  round_idx);
 209:     logic [63:0] key_out;
 210:     // rotate by 61 to the left
 211:     key_out = 64'(key_in << 61) | 64'(key_in >> (64-61));
 212:     // sbox on uppermost 4 bits
 213:     key_out[63 -: 4] = PRESENT_SBOX4[key_out[63 -: 4]];
 214:     // xor in round counter on bits 19 to 15
 215:     key_out[19:15] ^= round_idx;
 216:     return key_out;
 217:   endfunction : present_update_key64
 218: 
 219:   function automatic logic [79:0] present_update_key80(logic [79:0] key_in,
 220:                                                        logic [4:0]  round_idx);
 221:     logic [79:0] key_out;
 222:     // rotate by 61 to the left
 223:     key_out = 80'(key_in << 61) | 80'(key_in >> (80-61));
 224:     // sbox on uppermost 4 bits
 225:     key_out[79 -: 4] = PRESENT_SBOX4[key_out[79 -: 4]];
 226:     // xor in round counter on bits 19 to 15
 227:     key_out[19:15] ^= round_idx;
 228:     return key_out;
 229:   endfunction : present_update_key80
 230: 
 231:   function automatic logic [127:0] present_update_key128(logic [127:0] key_in,
 232:                                                          logic [4:0]   round_idx);
 233:     logic [127:0] key_out;
 234:     // rotate by 61 to the left
 235:     key_out = 128'(key_in << 61) | 128'(key_in >> (128-61));
 236:     // sbox on uppermost 4 bits
 237:     key_out[127 -: 4] = PRESENT_SBOX4[key_out[127 -: 4]];
 238:     // xor in round counter on bits 19 to 15
 239:     key_out[19:15] ^= round_idx;
 240:     return key_out;
 241:   endfunction : present_update_key128
 242: 
 243: 
 244:   // inverse key schedule
 245:   function automatic logic [63:0] present_inv_update_key64(logic [63:0] key_in,
 246:                                                            logic [4:0]  round_idx,
 247:                                                            // total number of rounds employed
 248:                                                            logic [4:0]  round_cnt);
 249:     logic [63:0] key_out;
 250:     // xor in round counter on bits 19 to 15
 251:     key_out[19:15] ^= 6'(round_cnt) + 1 - round_idx;
 252:     // sbox on uppermost 4 bits
 253:     key_out[63 -: 4] = PRESENT_SBOX4_INV[key_out[63 -: 4]];
 254:     // rotate by 61 to the right
 255:     key_out = 64'(key_in >> 61) | 64'(key_in << (64-61));
 256:     return key_out;
 257:   endfunction : present_inv_update_key64
 258: 
 259:   function automatic logic [79:0] present_inv_update_key80(logic [79:0] key_in,
 260:                                                            logic [4:0]  round_idx,
 261:                                                            // total number of rounds employed
 262:                                                            logic [4:0]  round_cnt);
 263:     logic [79:0] key_out;
 264:     // xor in round counter on bits 19 to 15
 265:     key_out[19:15] ^= 6'(round_cnt) + 1 - round_idx;
 266:     // sbox on uppermost 4 bits
 267:     key_out[79 -: 4] = PRESENT_SBOX4_INV[key_out[79 -: 4]];
 268:     // rotate by 61 to the right
 269:     key_out = 80'(key_in >> 61) | 80'(key_in << (80-61));
 270:     return key_out;
 271:   endfunction : present_inv_update_key80
 272: 
 273:   function automatic logic [127:0] present_inv_update_key128(logic [127:0] key_in,
 274:                                                              logic [4:0]   round_idx,
 275:                                                              // total number of rounds employed
 276:                                                              logic [4:0]   round_cnt);
 277:     logic [127:0] key_out;
 278:     // xor in round counter on bits 19 to 15
 279:     key_out[19:15] ^= 6'(round_cnt) + 1 - round_idx;
 280:     // sbox on uppermost 4 bits
 281:     key_out[127 -: 4] = PRESENT_SBOX4_INV[key_out[127 -: 4]];
 282:     // rotate by 61 to the right
 283:     key_out = 128'(key_in >> 61) | 128'(key_in << (128-61));
 284:     return key_out;
 285:   endfunction : present_inv_update_key128
 286: 
 287: 
 288:   // these functions can be used to derive the DEC key from the ENC key by
 289:   // stepping the key by the correct number of rounds using the keyschedule functions above.
 290:   function automatic logic [63:0] present_get_dec_key64(logic [63:0] key_in,
 291:                                                         // total number of rounds employed
 292:                                                         logic [4:0]  round_cnt);
 293:     logic [63:0] key_out;
 294:     key_out = key_in;
 295:     for (int k = 0; k < round_cnt; k++) begin
 296:       key_out = present_update_key64(key_out, 5'(k + 1));
 297:     end
 298:     return key_out;
 299:   endfunction : present_get_dec_key64
 300: 
 301:   function automatic logic [79:0] present_get_dec_key80(logic [79:0] key_in,
 302:                                                         // total number of rounds employed
 303:                                                         logic [4:0]  round_cnt);
 304:     logic [79:0] key_out;
 305:     key_out = key_in;
 306:     for (int k = 0; k < round_cnt; k++) begin
 307:       key_out = present_update_key80(key_out, 5'(k + 1));
 308:     end
 309:     return key_out;
 310:   endfunction : present_get_dec_key80
 311: 
 312:   function automatic logic [127:0] present_get_dec_key128(logic [127:0] key_in,
 313:                                                           // total number of rounds employed
 314:                                                           logic [4:0]   round_cnt);
 315:     logic [127:0] key_out;
 316:     key_out = key_in;
 317:     for (int k = 0; k < round_cnt; k++) begin
 318:       key_out = present_update_key128(key_out, 5'(k + 1));
 319:     end
 320:     return key_out;
 321:   endfunction : present_get_dec_key128
 322: 
 323:   /////////////////////////
 324:   // Common Subfunctions //
 325:   /////////////////////////
 326: 
 327:   function automatic logic [31:0] sbox4_32bit(logic [31:0] state_in, logic [15:0][3:0] sbox4);
 328:     logic [31:0] state_out;
 329:     // note that if simulation performance becomes an issue, this loop can be unrolled
 330:     for (int k = 0; k < 32/4; k++) begin
 331:       state_out[k*4  +: 4] = sbox4[state_in[k*4  +: 4]];
 332:     end
 333:     return state_out;
 334:   endfunction : sbox4_32bit
 335: 
 336:   function automatic logic [63:0] sbox4_64bit(logic [63:0] state_in, logic [15:0][3:0] sbox4);
 337:     logic [63:0] state_out;
 338:     // note that if simulation performance becomes an issue, this loop can be unrolled
 339:     for (int k = 0; k < 64/4; k++) begin
 340:       state_out[k*4  +: 4] = sbox4[state_in[k*4  +: 4]];
 341:     end
 342:     return state_out;
 343:   endfunction : sbox4_64bit
 344: 
 345:   function automatic logic [31:0] perm_32bit(logic [31:0] state_in, logic [31:0][4:0] perm);
 346:     logic [31:0] state_out;
 347:     // note that if simulation performance becomes an issue, this loop can be unrolled
 348:     for (int k = 0; k < 32; k++) begin
 349:       state_out[k] = state_in[perm[k]];
 350:     end
 351:     return state_out;
 352:   endfunction : perm_32bit
 353: 
 354:   function automatic logic [63:0] perm_64bit(logic [63:0] state_in, logic [63:0][5:0] perm);
 355:     logic [63:0] state_out;
 356:     // note that if simulation performance becomes an issue, this loop can be unrolled
 357:     for (int k = 0; k < 64; k++) begin
 358:       state_out[k] = state_in[perm[k]];
 359:     end
 360:     return state_out;
 361:   endfunction : perm_64bit
 362: 
 363: endpackage : prim_cipher_pkg
 364: