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