1/*
2 * Copyright (c) 2018 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Matt Horsnell
38 *          Prakash Ramrakhyani
39 */
40
41#include <cstdio>
42#include <iostream>
43#include <string>
44
45#include "crypto.hh"
46
47namespace ArmISA {
48
49const uint8_t
50Crypto::aesSBOX[256] = {
51    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
52    0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
53    0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
54    0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
55    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
56    0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
57    0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
58    0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
59    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
60    0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
61    0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
62    0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
63    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
64    0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
65    0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
66    0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
67    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
68    0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
69    0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
70    0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
71    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
72    0xb0, 0x54, 0xbb, 0x16
73};
74
75const uint8_t
76Crypto::aesInvSBOX[256] = {
77    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
78    0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
79    0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
80    0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
81    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
82    0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
83    0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
84    0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
85    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
86    0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
87    0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
88    0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
89    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
90    0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
91    0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
92    0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
93    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
94    0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
95    0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
96    0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
97    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
98    0x55, 0x21, 0x0c, 0x7d
99};
100
101const uint8_t
102Crypto::aesFFLOG[256] = {
103    0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68,
104    0x33, 0xee, 0xdf, 0x03, 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef,
105    0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1, 0x7d, 0xc2, 0x1d, 0xb5,
106    0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
107    0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45,
108    0x35, 0x93, 0xda, 0x8e, 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94,
109    0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38, 0x66, 0xdd, 0xfd, 0x30,
110    0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
111    0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54,
112    0xfa, 0x85, 0x3d, 0xba, 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca,
113    0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57, 0xaf, 0x58, 0xa8, 0x50,
114    0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
115    0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0,
116    0x9c, 0xa9, 0x51, 0xa0, 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec,
117    0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7, 0xcc, 0xbb, 0x3e, 0x5a,
118    0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
119    0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd,
120    0x37, 0x3f, 0x5b, 0xd1, 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47,
121    0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab, 0x44, 0x11, 0x92, 0xd9,
122    0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
123    0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80,
124    0xc0, 0xf7, 0x70, 0x07
125};
126
127const uint8_t
128Crypto::aesFFEXP[256] = {
129    0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, 0x1a, 0x2e, 0x72, 0x96,
130    0xa1, 0xf8, 0x13, 0x35, 0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4,
131    0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa, 0xe5, 0x34, 0x5c, 0xe4,
132    0x37, 0x59, 0xeb, 0x26, 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31,
133    0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, 0x4f, 0xd1, 0x68, 0xb8,
134    0xd3, 0x6e, 0xb2, 0xcd, 0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7,
135    0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88, 0x83, 0x9e, 0xb9, 0xd0,
136    0x6b, 0xbd, 0xdc, 0x7f, 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a,
137    0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, 0x0b, 0x1d, 0x27, 0x69,
138    0xbb, 0xd6, 0x61, 0xa3, 0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec,
139    0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0, 0xfb, 0x16, 0x3a, 0x4e,
140    0xd2, 0x6d, 0xb7, 0xc2, 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41,
141    0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, 0x5b, 0xed, 0x2c, 0x74,
142    0x9c, 0xbf, 0xda, 0x75, 0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e,
143    0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80, 0x9b, 0xb6, 0xc1, 0x58,
144    0xe8, 0x23, 0x65, 0xaf, 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54,
145    0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, 0x1b, 0x2d, 0x77, 0x99,
146    0xb0, 0xcb, 0x46, 0xca, 0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91,
147    0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e, 0x12, 0x36, 0x5a, 0xee,
148    0x29, 0x7b, 0x8d, 0x8c, 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17,
149    0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, 0x1c, 0x24, 0x6c, 0xb4,
150    0xc7, 0x52, 0xf6, 0x01
151};
152
153const uint8_t
154Crypto::aesSHIFT[16] = {
155    0, 5, 10, 15, 4, 9, 14, 3,
156    8, 13, 2, 7, 12, 1, 6, 11
157};
158
159const uint8_t
160Crypto::aesINVSHIFT[16] = {
161    0, 13, 10, 7, 4, 1, 14, 11,
162    8, 5, 2, 15, 12, 9, 6, 3
163};
164
165uint8_t
166Crypto::aesFFMul(uint8_t a, uint8_t b)
167{
168    unsigned int log_prod;
169
170    if ((a ==0)|| (b == 0)) return 0;
171
172    log_prod = (aesFFLOG[a] + aesFFLOG[b]);
173
174    if(log_prod > 0xff)
175        log_prod = log_prod - 0xff;
176
177    return aesFFEXP[log_prod];
178}
179
180void
181Crypto::aesSubBytes(uint8_t *output, uint8_t *input)
182{
183    for (int i = 0; i < 16; ++i) {
184        output[i] = aesSBOX[input[i]];
185    }
186}
187
188void
189Crypto::aesInvSubBytes(uint8_t *output, uint8_t *input)
190{
191    for (int i = 0; i < 16; ++i) {
192        output[i] = aesInvSBOX[input[i]];
193    }
194}
195
196void
197Crypto::aesShiftRows(uint8_t *output, uint8_t *input)
198{
199    for (int i = 0; i < 16; ++i) {
200        output[i] = input[aesSHIFT[i]];
201    }
202}
203
204void
205Crypto::aesInvShiftRows(uint8_t *output, uint8_t *input)
206{
207    for (int i = 0; i < 16; ++i) {
208        output[i] = input[aesINVSHIFT[i]];
209    }
210}
211
212void
213Crypto::aesAddRoundKey(uint8_t *output, uint8_t *input,
214                    uint8_t *key)
215{
216    for (int i = 0; i < 16; ++i) {
217        output[i] = input[i] ^ key[i];
218    }
219}
220
221void
222Crypto::aesMixColumns(uint8_t *output, uint8_t *input)
223{
224    for (int j = 0; j < 4; ++j) {
225        int row0 = (j * 4);
226        int row1 = row0 + 1;
227        int row2 = row0 + 2;
228        int row3 = row0 + 3;
229        uint8_t t1 = input[row0] ^ input[row1] ^
230                           input[row2] ^ input[row3];
231
232        output[row1] = input[row1] ^ t1 ^ aesFFMul2(input[row1] ^ input[row2]);
233        output[row2] = input[row2] ^ t1 ^ aesFFMul2(input[row2] ^ input[row3]);
234        output[row3] = input[row3] ^ t1 ^ aesFFMul2(input[row3] ^ input[row0]);
235        output[row0] = input[row0] ^ t1 ^ aesFFMul2(input[row0] ^ input[row1]);
236    }
237}
238
239void
240Crypto::aesInvMixColumns(uint8_t *output, uint8_t *input)
241{
242    for (int j = 0; j < 4; ++j) {
243        for (int i = 0; i < 4; ++i) {
244            int index0 = (j * 4) + i;
245            int index1 = (j * 4) + ((i + 1) % 4);
246            int index2 = (j * 4) + ((i + 2) % 4);
247            int index3 = (j * 4) + ((i + 3) % 4);
248            output [index0] =
249                aesFFMul(0x0e, input[index0]) ^ aesFFMul(0x0b, input[index1]) ^
250                aesFFMul(0x0d, input[index2]) ^ aesFFMul(0x09, input[index3]);
251            }
252    }
253}
254
255void
256Crypto::aesEncrypt(uint8_t *output, uint8_t *input,
257                    uint8_t *key)
258{
259    uint8_t temp1[16];
260    uint8_t temp2[16];
261    aesAddRoundKey(&temp1[0], input, key);
262    aesShiftRows(&temp2[0], &temp1[0]);
263    aesSubBytes(output, &temp2[0]);
264}
265
266void
267Crypto::aesDecrypt(uint8_t *output, uint8_t *input,
268                    uint8_t *key)
269{
270    uint8_t temp1[16];
271    uint8_t temp2[16];
272    aesAddRoundKey(&temp1[0], input, key);
273    aesInvShiftRows(&temp2[0], &temp1[0]);
274    aesInvSubBytes(output, &temp2[0]);
275}
276
277void
278Crypto::sha256Op(
279    uint32_t *X,
280    uint32_t *Y,
281    uint32_t *Z)
282{
283    uint32_t T0, T1, T2, T3;
284    for (int i = 0; i < 4; ++i) {
285        T0 = choose(Y[0], Y[1], Y[2]);
286        T1 = majority(X[0], X[1], X[2]);
287        T2 = Y[3] + sigma1(Y[0]) + T0 + Z[i];
288        X[3] = T2 + X[3];
289        Y[3] = T2 + sigma0(X[0]) + T1;
290        // Rotate
291        T3 = Y[3];
292        Y[3] = Y[2]; Y[2] = Y[1]; Y[1] = Y[0]; Y[0] = X[3];
293        X[3] = X[2]; X[2] = X[1]; X[1] = X[0]; X[0] = T3;
294    }
295}
296
297void
298Crypto::_sha1Op(
299    uint32_t *X,
300    uint32_t *Y,
301    uint32_t *Z,
302    SHAOp op)
303{
304    uint32_t T1, T2;
305
306    for (int i = 0; i < 4; ++i) {
307        switch (op) {
308          case CHOOSE:   T1 = choose(X[1], X[2], X[3]); break;
309          case PARITY:   T1 = parity(X[1], X[2], X[3]); break;
310          case MAJORITY: T1 = majority(X[1], X[2], X[3]); break;
311          default: return;
312        }
313        Y[0] += ror(X[0], 27) + T1 + Z[i];
314        X[1] = ror(X[1], 2);
315        T2 = Y[0];
316        Y[0] = X[3];
317        X[3] = X[2]; X[2] = X[1]; X[1] = X[0]; X[0] = T2;
318    }
319}
320
321void
322Crypto::sha256H(
323    uint8_t *output,
324    uint8_t *input,
325    uint8_t *input2)
326{
327    uint32_t X[4], Y[4], Z[4];
328    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
329    sha256Op(&X[0], &Y[0], &Z[0]);
330    store1Reg(output, &X[0]);
331}
332
333void
334Crypto::sha256H2(
335    uint8_t *output,
336    uint8_t *input,
337    uint8_t *input2)
338{
339    uint32_t X[4], Y[4], Z[4];
340    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
341    sha256Op(&Y[0], &X[0], &Z[0]);
342    store1Reg(output, &X[0]);
343}
344
345void
346Crypto::sha256Su0(uint8_t *output, uint8_t *input)
347{
348    uint32_t X[4], Y[4];
349    uint32_t T[4];
350
351    load2Reg(&X[0], &Y[0], output, input);
352
353    T[3] = Y[0]; T[2] = X[3]; T[1] = X[2]; T[0] = X[1];
354
355    T[3] = ror(T[3], 7) ^ ror(T[3], 18) ^ (T[3] >> 3);
356    T[2] = ror(T[2], 7) ^ ror(T[2], 18) ^ (T[2] >> 3);
357    T[1] = ror(T[1], 7) ^ ror(T[1], 18) ^ (T[1] >> 3);
358    T[0] = ror(T[0], 7) ^ ror(T[0], 18) ^ (T[0] >> 3);
359
360    X[3] += T[3];
361    X[2] += T[2];
362    X[1] += T[1];
363    X[0] += T[0];
364
365    store1Reg(output, &X[0]);
366}
367
368void
369Crypto::sha256Su1(
370    uint8_t *output,
371    uint8_t *input,
372    uint8_t *input2)
373{
374    uint32_t X[4], Y[4], Z[4];
375    uint32_t T0[4], T1[4], T2[4], T3[4];
376
377    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
378
379    T0[3] = Z[0]; T0[2] = Y[3]; T0[1] = Y[2]; T0[0] = Y[1];
380    T1[1] = Z[3]; T1[0] = Z[2];
381    T1[1] = ror(T1[1], 17) ^ ror(T1[1], 19) ^ (T1[1] >> 10);
382    T1[0] = ror(T1[0], 17) ^ ror(T1[0], 19) ^ (T1[0] >> 10);
383    T3[1] = X[1] + T0[1]; T3[0] = X[0] + T0[0];
384    T1[1] = T3[1] + T1[1]; T1[0] = T3[0] + T1[0];
385    T2[1] = ror(T1[1], 17) ^ ror(T1[1], 19) ^ (T1[1] >> 10);
386    T2[0] = ror(T1[0], 17) ^ ror(T1[0], 19) ^ (T1[0] >> 10);
387    T3[1] = X[3] + T0[3]; T3[0] = X[2] + T0[2];
388    X[3] = T3[1] + T2[1];
389    X[2] = T3[0] + T2[0];
390    X[1] = T1[1]; X[0] = T1[0];
391
392    store1Reg(output, &X[0]);
393}
394
395void
396Crypto::sha1Op(
397    uint8_t *output,
398    uint8_t *input,
399    uint8_t *input2,
400    SHAOp op)
401{
402    uint32_t X[4], Y[4], Z[4];
403    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
404    _sha1Op(&X[0], &Y[0], &Z[0], op);
405    store1Reg(output, &X[0]);
406}
407
408void
409Crypto::sha1C(
410    uint8_t *output,
411    uint8_t *input,
412    uint8_t *input2)
413{
414    sha1Op(output, input, input2, CHOOSE);
415}
416
417void
418Crypto::sha1P(
419    uint8_t *output,
420    uint8_t *input,
421    uint8_t *input2)
422{
423    sha1Op(output, input, input2, PARITY);
424}
425
426void
427Crypto::sha1M(
428    uint8_t *output,
429    uint8_t *input,
430    uint8_t *input2)
431{
432    sha1Op(output, input, input2, MAJORITY);
433}
434
435void
436Crypto::sha1H(uint8_t *output, uint8_t *input)
437{
438    uint32_t X[4], Y[4];
439    load2Reg(&X[0], &Y[0], output, input);
440    X[0] = ror(Y[0], 2);
441    store1Reg(output, &X[0]);
442}
443
444void
445Crypto::sha1Su0(
446    uint8_t *output,
447    uint8_t *input,
448    uint8_t *input2)
449{
450    uint32_t X[4], Y[4], Z[4], T[4];
451    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
452
453    T[3] = Y[1]; T[2] = Y[0]; T[1] = X[3]; T[0] = X[2];
454    X[3] = T[3] ^ X[3] ^ Z[3];
455    X[2] = T[2] ^ X[2] ^ Z[2];
456    X[1] = T[1] ^ X[1] ^ Z[1];
457    X[0] = T[0] ^ X[0] ^ Z[0];
458
459    store1Reg(output, &X[0]);
460}
461
462void
463Crypto::sha1Su1(uint8_t *output, uint8_t *input)
464{
465    uint32_t X[4], Y[4], T[4];
466    load2Reg(&X[0], &Y[0], output, input);
467
468    T[3] = X[3] ^ 0x0;
469    T[2] = X[2] ^ Y[3];
470    T[1] = X[1] ^ Y[2];
471    T[0] = X[0] ^ Y[1];
472    X[2] = ror(T[2], 31); X[1] = ror(T[1], 31); X[0] = ror(T[0], 31);
473    X[3] = ror(T[3], 31) ^ ror(T[0], 30);
474
475    store1Reg(output, &X[0]);
476}
477
478void
479Crypto::load2Reg(
480    uint32_t *X,
481    uint32_t *Y,
482    uint8_t *output,
483    uint8_t *input)
484{
485    for (int i = 0; i < 4; ++i) {
486        X[i] = *((uint32_t *)&output[i*4]);
487        Y[i] = *((uint32_t *)&input[i*4]);
488    }
489}
490
491void
492Crypto::load3Reg(
493    uint32_t *X,
494    uint32_t *Y,
495    uint32_t *Z,
496    uint8_t *output,
497    uint8_t *input,
498    uint8_t *input2)
499{
500    for (int i = 0; i < 4; ++i) {
501        X[i] = *((uint32_t *)&output[i*4]);
502        Y[i] = *((uint32_t *)&input[i*4]);
503        Z[i] = *((uint32_t *)&input2[i*4]);
504    }
505}
506
507void
508Crypto::store1Reg(uint8_t *output, uint32_t *X)
509{
510    for (int i = 0; i < 4; ++i) {
511        output[i*4] = (uint8_t)(X[i]);
512        output[i*4+1] = (uint8_t)(X[i] >> 8);
513        output[i*4+2] = (uint8_t)(X[i] >> 16);
514        output[i*4+3] = (uint8_t)(X[i] >> 24);
515    }
516}
517
518} // namespace ArmISA
519