hw/ip/aes/rtl/aes_sbox_canright.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 Canright SBox #4
6: //
7: // For details, see the technical report: Canright, "A very compact Rijndael S-box"
8: // available at https://hdl.handle.net/10945/25608
9:
10: module aes_sbox_canright (
11: input aes_pkg::mode_e mode_i,
12: input logic [7:0] data_i,
13: output logic [7:0] data_o
14: );
15:
16: import aes_pkg::*;
17:
18: ///////////////////////////
19: // Functions & Constants //
20: ///////////////////////////
21:
22: // Multiplication in GF(2^2), using normal basis [Omega^2, Omega]
23: // (see Figure 14 in the technical report)
24: function automatic logic [1:0] aes_mul_gf2p2(input logic [1:0] g, input logic [1:0] d);
25: logic [1:0] f;
26: logic a, b, c;
27: a = g[1] & d[1];
28: b = (^g) & (^d);
29: c = g[0] & d[0];
30: f[1] = a ^ b;
31: f[0] = c ^ b;
32: return f;
33: endfunction
34:
35: // Scale by Omega^2 = N in GF(2^2), using normal basis [Omega^2, Omega]
36: // (see Figure 16 in the technical report)
37: function automatic logic [1:0] aes_scale_omega2_gf2p2(input logic [1:0] g);
38: logic [1:0] d;
39: d[1] = g[0];
40: d[0] = g[1] ^ g[0];
41: return d;
42: endfunction
43:
44: // Scale by Omega = N^2 in GF(2^2), using normal basis [Omega^2, Omega]
45: // (see Figure 15 in the technical report)
46: function automatic logic [1:0] aes_scale_omega_gf2p2(input logic [1:0] g);
47: logic [1:0] d;
48: d[1] = g[1] ^ g[0];
49: d[0] = g[1];
50: return d;
51: endfunction
52:
53: // Square in GF(2^2), using normal basis [Omega^2, Omega]
54: // (see Figures 8 and 10 in the technical report)
55: function automatic logic [1:0] aes_square_gf2p2(input logic [1:0] g);
56: logic [1:0] d;
57: d[1] = g[0];
58: d[0] = g[1];
59: return d;
60: endfunction
61:
62: // Multiplication in GF(2^4), using normal basis [alpha^8, alpha^2]
63: // (see Figure 13 in the technical report)
64: function automatic logic [3:0] aes_mul_gf2p4(input logic [3:0] gamma, input logic [3:0] delta);
65: logic [3:0] theta;
66: logic [1:0] a, b, c;
67: a = aes_mul_gf2p2(gamma[3:2], delta[3:2]);
68: b = aes_mul_gf2p2(gamma[3:2] ^ gamma[1:0], delta[3:2] ^ delta[1:0]);
69: c = aes_mul_gf2p2(gamma[1:0], delta[1:0]);
70: theta[3:2] = a ^ aes_scale_omega2_gf2p2(b);
71: theta[1:0] = c ^ aes_scale_omega2_gf2p2(b);
72: return theta;
73: endfunction
74:
75: // Square and scale by nu in GF(2^4)/GF(2^2), using normal basis [alpha^8, alpha^2]
76: // (see Figure 19 as well as Appendix A of the technical report)
77: function automatic logic [3:0] aes_square_scale_gf2p4_gf2p2(input logic [3:0] gamma);
78: logic [3:0] delta;
79: logic [1:0] a, b;
80: a = gamma[3:2] ^ gamma[1:0];
81: b = aes_square_gf2p2(gamma[1:0]);
82: delta[3:2] = aes_square_gf2p2(a);
83: delta[1:0] = aes_scale_omega_gf2p2(b);
84: return delta;
85: endfunction
86:
87: // Inverse in GF(2^4), using normal basis [alpha^8, alpha^2]
88: // (see Figure 12 in the technical report)
89: function automatic logic [3:0] aes_inverse_gf2p4(input logic [3:0] gamma);
90: logic [3:0] delta;
91: logic [1:0] a, b, c, d;
92: a = gamma[3:2] ^ gamma[1:0];
93: b = aes_mul_gf2p2(gamma[3:2], gamma[1:0]);
94: c = aes_scale_omega2_gf2p2(aes_square_gf2p2(a));
95: d = aes_square_gf2p2(c ^ b);
96: delta[3:2] = aes_mul_gf2p2(d, gamma[1:0]);
97: delta[1:0] = aes_mul_gf2p2(d, gamma[3:2]);
98: return delta;
99: endfunction
100:
101: // Inverse in GF(2^8), using normal basis [d^16, d]
102: // (see Figure 11 in the technical report)
103: function automatic logic [7:0] aes_inverse_gf2p8(input logic [7:0] gamma);
104: logic [7:0] delta;
105: logic [3:0] a, b, c, d;
106: a = gamma[7:4] ^ gamma[3:0];
107: b = aes_mul_gf2p4(gamma[7:4], gamma[3:0]);
108: c = aes_square_scale_gf2p4_gf2p2(a);
109: d = aes_inverse_gf2p4(c ^ b);
110: delta[7:4] = aes_mul_gf2p4(d, gamma[3:0]);
111: delta[3:0] = aes_mul_gf2p4(d, gamma[7:4]);
112: return delta;
113: endfunction
114:
115: // Basis conversion matrices to convert between polynomial basis A, normal basis X
116: // and basis S incorporating the bit matrix of the SBox. More specifically,
117: // multiplication by x2s performs the transformation from normal basis X into
118: // polynomial basis A, followed by the affine transformation (substep 2). Likewise,
119: // multiplication by s2x performs the inverse affine transformation followed by the
120: // transformation from polynomial basis A to normal basis X.
121: // (see Appendix A of the technical report)
122: const logic [7:0] a2x [8] = '{8'h98, 8'hf3, 8'hf2, 8'h48, 8'h09, 8'h81, 8'ha9, 8'hff};
123: const logic [7:0] x2a [8] = '{8'h64, 8'h78, 8'h6e, 8'h8c, 8'h68, 8'h29, 8'hde, 8'h60};
124: const logic [7:0] x2s [8] = '{8'h58, 8'h2d, 8'h9e, 8'h0b, 8'hdc, 8'h04, 8'h03, 8'h24};
125: const logic [7:0] s2x [8] = '{8'h8c, 8'h79, 8'h05, 8'heb, 8'h12, 8'h04, 8'h51, 8'h53};
126:
127: ///////////////////
128: // Canright SBox //
129: ///////////////////
130:
131: logic [7:0] data_basis_x, data_inverse;
132:
133: // Convert to normal basis X.
134: assign data_basis_x = (mode_i == AES_ENC) ? aes_mvm(data_i, a2x) :
135: aes_mvm(data_i ^ 8'h63, s2x);
136:
137: // Do the inversion in normal basis X.
138: assign data_inverse = aes_inverse_gf2p8(data_basis_x);
139:
140: // Convert to basis S or A.
141: assign data_o = (mode_i == AES_ENC) ? aes_mvm(data_inverse, x2s) ^ 8'h63 :
142: aes_mvm(data_inverse, x2a);
143:
144: endmodule
145: