1 /////////////////////////////////////////////////////////////////////////
2 // $Id: sha.cc 13690 2019-12-19 19:20:13Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2013-2019 Stanislav Shwartsman
6 // Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
21 //
22 /////////////////////////////////////////////////////////////////////////
23
24 #define NEED_CPU_REG_SHORTCUTS 1
25 #include "bochs.h"
26 #include "cpu.h"
27 #define LOG_THIS BX_CPU_THIS_PTR
28
29 #if BX_CPU_LEVEL >= 6
30
31 //
32 // sha_f0(): A bit oriented logical operation that derives a new dword from three SHA1 state variables (dword).
33 // This function is used in SHA1 round 1 to 20 processing:
34 //
35 // f0(B,C,D) := (B AND C) XOR ((NOT(B) AND D)
36 //
37
sha_f0(Bit32u B,Bit32u C,Bit32u D)38 BX_CPP_INLINE Bit32u sha_f0(Bit32u B, Bit32u C, Bit32u D)
39 {
40 return (B & C) ^ (~B & D);
41 }
42
43 //
44 // sha_f1(): A bit oriented logical operation that derives a new dword from three SHA1 state variables (dword).
45 // This function is used in SHA1 round 21 to 40 processing:
46 //
47 // f1(B,C,D) := B XOR C XOR D
48 //
49
sha_f1(Bit32u B,Bit32u C,Bit32u D)50 BX_CPP_INLINE Bit32u sha_f1(Bit32u B, Bit32u C, Bit32u D)
51 {
52 return (B ^ C ^ D);
53 }
54
55 //
56 // sha_f2(): A bit oriented logical operation that derives a new dword from three SHA1 state variables (dword).
57 // This function is used in SHA1 round 41 to 60 processing:
58 //
59 // f2(B,C,D) := (B AND C) XOR (B AND D) XOR (C AND D)
60 //
61
sha_f2(Bit32u B,Bit32u C,Bit32u D)62 BX_CPP_INLINE Bit32u sha_f2(Bit32u B, Bit32u C, Bit32u D)
63 {
64 return (B & C) ^ (B & D) ^ (C & D);
65 }
66
67 //
68 // sha_f3(): A bit oriented logical operation that derives a new dword from three SHA1 state variables (dword).
69 // This function is used in SHA1 round 61 to 80 processing:
70 //
71 // f3(B,C,D) := B XOR C XOR D
72 //
73 // Yes, it is the same function as sha_f1()
74 //
75
sha_f(Bit32u B,Bit32u C,Bit32u D,unsigned index)76 BX_CPP_INLINE Bit32u sha_f(Bit32u B, Bit32u C, Bit32u D, unsigned index)
77 {
78 if (index == 0)
79 return sha_f0(B,C,D);
80 if (index == 2)
81 return sha_f2(B,C,D);
82
83 // sha_f3() and sha_f1() are the same
84 return sha_f1(B,C,D);
85 }
86
87 //
88 // sha_ch(): A bit oriented logical operation that derives a new dword from three SHA256 state variables (dword).
89 //
90 // Ch(E,F,G) := (E AND F) XOR ((NOT E) AND G)
91 //
92 // Yes, it is the same as sha_f0()
93 //
94
95 #define sha_ch(E,F,G) sha_f0((E), (F), (G))
96
97 //
98 // sha_maj(): A bit oriented logical operation that derives a new dword from three SHA256 state variables (dword).
99 //
100 // Maj(A,B,C) := (A AND B) XOR (A AND C) XOR (B AND C)
101 //
102 // Yes, it is the same as sha_f2()
103 //
104
105 #define sha_maj(A,B,C) sha_f2((A), (B), (C))
106
rotate_r(Bit32u val_32,unsigned count)107 BX_CPP_INLINE Bit32u rotate_r(Bit32u val_32, unsigned count)
108 {
109 return (val_32 >> count) | (val_32 << (32-count));
110 }
111
rotate_l(Bit32u val_32,unsigned count)112 BX_CPP_INLINE Bit32u rotate_l(Bit32u val_32, unsigned count)
113 {
114 return (val_32 << count) | (val_32 >> (32-count));
115 }
116
117 // A bit oriented logical and rotational transformation performed on a dword for SHA256
sha256_transformation_rrr(Bit32u val_32,unsigned rotate1,unsigned rotate2,unsigned rotate3)118 BX_CPP_INLINE Bit32u sha256_transformation_rrr(Bit32u val_32, unsigned rotate1, unsigned rotate2, unsigned rotate3)
119 {
120 return rotate_r(val_32, rotate1) ^ rotate_r(val_32, rotate2) ^ rotate_r(val_32, rotate3);
121 }
122
sha256_transformation_rrs(Bit32u val_32,unsigned rotate1,unsigned rotate2,unsigned shr)123 BX_CPP_INLINE Bit32u sha256_transformation_rrs(Bit32u val_32, unsigned rotate1, unsigned rotate2, unsigned shr)
124 {
125 return rotate_r(val_32, rotate1) ^ rotate_r(val_32, rotate2) ^ (val_32 >> shr);
126 }
127
128 /* 0F 38 C8 */
SHA1NEXTE_VdqWdqR(bxInstruction_c * i)129 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHA1NEXTE_VdqWdqR(bxInstruction_c *i)
130 {
131 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src());
132
133 op2.xmm32u(3) += rotate_l(op1.xmm32u(3), 30);
134
135 BX_WRITE_XMM_REG(i->dst(), op2);
136
137 BX_NEXT_INSTR(i);
138 }
139
140 /* 0F 38 C9 */
SHA1MSG1_VdqWdqR(bxInstruction_c * i)141 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHA1MSG1_VdqWdqR(bxInstruction_c *i)
142 {
143 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src());
144
145 op1.xmm32u(3) ^= op1.xmm32u(1);
146 op1.xmm32u(2) ^= op1.xmm32u(0);
147 op1.xmm32u(1) ^= op2.xmm32u(3);
148 op1.xmm32u(0) ^= op2.xmm32u(2);
149
150 BX_WRITE_XMM_REG(i->dst(), op1);
151
152 BX_NEXT_INSTR(i);
153 }
154
155 /* 0F 38 CA */
SHA1MSG2_VdqWdqR(bxInstruction_c * i)156 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHA1MSG2_VdqWdqR(bxInstruction_c *i)
157 {
158 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src());
159
160 op1.xmm32u(3) = rotate_l(op1.xmm32u(3) ^ op2.xmm32u(2), 1);
161 op1.xmm32u(2) = rotate_l(op1.xmm32u(2) ^ op2.xmm32u(1), 1);
162 op1.xmm32u(1) = rotate_l(op1.xmm32u(1) ^ op2.xmm32u(0), 1);
163 op1.xmm32u(0) = rotate_l(op1.xmm32u(0) ^ op1.xmm32u(3), 1);
164
165 BX_WRITE_XMM_REG(i->dst(), op1);
166
167 BX_NEXT_INSTR(i);
168 }
169
170 /* 0F 38 CB */
SHA256RNDS2_VdqWdqR(bxInstruction_c * i)171 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHA256RNDS2_VdqWdqR(bxInstruction_c *i)
172 {
173 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()), wk = BX_READ_XMM_REG(0);
174
175 Bit32u A[3], B[3], C[3], D[3], E[3], F[3], G[3], H[3];
176
177 A[0] = op2.xmm32u(3);
178 B[0] = op2.xmm32u(2);
179 E[0] = op2.xmm32u(1);
180 F[0] = op2.xmm32u(0);
181
182 C[0] = op1.xmm32u(3);
183 D[0] = op1.xmm32u(2);
184 G[0] = op1.xmm32u(1);
185 H[0] = op1.xmm32u(0);
186
187 for (unsigned n=0; n < 2; n++) {
188 Bit32u tmp = sha_ch (E[n], F[n], G[n]) + sha256_transformation_rrr(E[n], 6, 11, 25) + wk.xmm32u(n) + H[n];
189 A[n+1] = tmp + sha_maj(A[n], B[n], C[n]) + sha256_transformation_rrr(A[n], 2, 13, 22);
190 B[n+1] = A[n];
191 C[n+1] = B[n];
192 D[n+1] = C[n];
193 E[n+1] = tmp + D[n];
194 F[n+1] = E[n];
195 G[n+1] = F[n];
196 H[n+1] = G[n];
197 }
198
199 op1.xmm32u(0) = F[2];
200 op1.xmm32u(1) = E[2];
201 op1.xmm32u(2) = B[2];
202 op1.xmm32u(3) = A[2];
203
204 BX_WRITE_XMM_REG(i->dst(), op1);
205
206 BX_NEXT_INSTR(i);
207 }
208
209 /* 0F 38 CC */
SHA256MSG1_VdqWdqR(bxInstruction_c * i)210 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHA256MSG1_VdqWdqR(bxInstruction_c *i)
211 {
212 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst());
213 Bit32u op2 = BX_READ_XMM_REG_LO_DWORD(i->src());
214
215 op1.xmm32u(0) += sha256_transformation_rrs(op1.xmm32u(1), 7, 18, 3);
216 op1.xmm32u(1) += sha256_transformation_rrs(op1.xmm32u(2), 7, 18, 3);
217 op1.xmm32u(2) += sha256_transformation_rrs(op1.xmm32u(3), 7, 18, 3);
218 op1.xmm32u(3) += sha256_transformation_rrs(op2, 7, 18, 3);
219
220 BX_WRITE_XMM_REG(i->dst(), op1);
221
222 BX_NEXT_INSTR(i);
223 }
224
225 /* 0F 38 CD */
SHA256MSG2_VdqWdqR(bxInstruction_c * i)226 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHA256MSG2_VdqWdqR(bxInstruction_c *i)
227 {
228 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src());
229
230 op1.xmm32u(0) += sha256_transformation_rrs(op2.xmm32u(2), 17, 19, 10);
231 op1.xmm32u(1) += sha256_transformation_rrs(op2.xmm32u(3), 17, 19, 10);
232 op1.xmm32u(2) += sha256_transformation_rrs(op1.xmm32u(0), 17, 19, 10);
233 op1.xmm32u(3) += sha256_transformation_rrs(op1.xmm32u(1), 17, 19, 10);
234
235 BX_WRITE_XMM_REG(i->dst(), op1);
236
237 BX_NEXT_INSTR(i);
238 }
239
240 /* 0F 3A CC */
SHA1RNDS4_VdqWdqIbR(bxInstruction_c * i)241 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHA1RNDS4_VdqWdqIbR(bxInstruction_c *i)
242 {
243 // SHA1 Constants dependent on immediate i
244 static const Bit32u sha_Ki[4] = { 0x5A827999, 0x6ED9EBA1, 0X8F1BBCDC, 0xCA62C1D6 };
245
246 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src());
247 unsigned imm = i->Ib() & 0x3;
248 Bit32u K = sha_Ki[imm];
249
250 Bit32u W[4] = { op2.xmm32u(3), op2.xmm32u(2), op2.xmm32u(1), op2.xmm32u(0) };
251 Bit32u A[5], B[5], C[5], D[5], E[5];
252
253 A[0] = op1.xmm32u(3);
254 B[0] = op1.xmm32u(2);
255 C[0] = op1.xmm32u(1);
256 D[0] = op1.xmm32u(0);
257 E[0] = 0;
258
259 for (unsigned n=0; n < 4; n++) {
260 A[n+1] = sha_f(B[n], C[n], D[n], imm) + rotate_l(A[n], 5) + W[n] + E[n] + K;
261 B[n+1] = A[n];
262 C[n+1] = rotate_l(B[n], 30);
263 D[n+1] = C[n];
264 E[n+1] = D[n];
265 }
266
267 op1.xmm32u(0) = A[4];
268 op1.xmm32u(1) = B[4];
269 op1.xmm32u(2) = C[4];
270 op1.xmm32u(3) = D[4];
271
272 BX_WRITE_XMM_REG(i->dst(), op1);
273
274 BX_NEXT_INSTR(i);
275 }
276
277 #endif
278