crypto.cc revision 13168:4965381c122d
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
49void
50Crypto::sha256Op(
51    uint32_t *X,
52    uint32_t *Y,
53    uint32_t *Z)
54{
55    uint32_t T0, T1, T2, T3;
56    for (int i = 0; i < 4; ++i) {
57        T0 = choose(Y[0], Y[1], Y[2]);
58        T1 = majority(X[0], X[1], X[2]);
59        T2 = Y[3] + sigma1(Y[0]) + T0 + Z[i];
60        X[3] = T2 + X[3];
61        Y[3] = T2 + sigma0(X[0]) + T1;
62        // Rotate
63        T3 = Y[3];
64        Y[3] = Y[2]; Y[2] = Y[1]; Y[1] = Y[0]; Y[0] = X[3];
65        X[3] = X[2]; X[2] = X[1]; X[1] = X[0]; X[0] = T3;
66    }
67}
68
69void
70Crypto::_sha1Op(
71    uint32_t *X,
72    uint32_t *Y,
73    uint32_t *Z,
74    SHAOp op)
75{
76    uint32_t T1, T2;
77
78    for (int i = 0; i < 4; ++i) {
79        switch (op) {
80          case CHOOSE:   T1 = choose(X[1], X[2], X[3]); break;
81          case PARITY:   T1 = parity(X[1], X[2], X[3]); break;
82          case MAJORITY: T1 = majority(X[1], X[2], X[3]); break;
83          default: return;
84        }
85        Y[0] += ror(X[0], 27) + T1 + Z[i];
86        X[1] = ror(X[1], 2);
87        T2 = Y[0];
88        Y[0] = X[3];
89        X[3] = X[2]; X[2] = X[1]; X[1] = X[0]; X[0] = T2;
90    }
91}
92
93void
94Crypto::sha256H(
95    uint8_t *output,
96    uint8_t *input,
97    uint8_t *input2)
98{
99    uint32_t X[4], Y[4], Z[4];
100    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
101    sha256Op(&X[0], &Y[0], &Z[0]);
102    store1Reg(output, &X[0]);
103}
104
105void
106Crypto::sha256H2(
107    uint8_t *output,
108    uint8_t *input,
109    uint8_t *input2)
110{
111    uint32_t X[4], Y[4], Z[4];
112    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
113    sha256Op(&Y[0], &X[0], &Z[0]);
114    store1Reg(output, &X[0]);
115}
116
117void
118Crypto::sha256Su0(uint8_t *output, uint8_t *input)
119{
120    uint32_t X[4], Y[4];
121    uint32_t T[4];
122
123    load2Reg(&X[0], &Y[0], output, input);
124
125    T[3] = Y[0]; T[2] = X[3]; T[1] = X[2]; T[0] = X[1];
126
127    T[3] = ror(T[3], 7) ^ ror(T[3], 18) ^ (T[3] >> 3);
128    T[2] = ror(T[2], 7) ^ ror(T[2], 18) ^ (T[2] >> 3);
129    T[1] = ror(T[1], 7) ^ ror(T[1], 18) ^ (T[1] >> 3);
130    T[0] = ror(T[0], 7) ^ ror(T[0], 18) ^ (T[0] >> 3);
131
132    X[3] += T[3];
133    X[2] += T[2];
134    X[1] += T[1];
135    X[0] += T[0];
136
137    store1Reg(output, &X[0]);
138}
139
140void
141Crypto::sha256Su1(
142    uint8_t *output,
143    uint8_t *input,
144    uint8_t *input2)
145{
146    uint32_t X[4], Y[4], Z[4];
147    uint32_t T0[4], T1[4], T2[4], T3[4];
148
149    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
150
151    T0[3] = Z[0]; T0[2] = Y[3]; T0[1] = Y[2]; T0[0] = Y[1];
152    T1[1] = Z[3]; T1[0] = Z[2];
153    T1[1] = ror(T1[1], 17) ^ ror(T1[1], 19) ^ (T1[1] >> 10);
154    T1[0] = ror(T1[0], 17) ^ ror(T1[0], 19) ^ (T1[0] >> 10);
155    T3[1] = X[1] + T0[1]; T3[0] = X[0] + T0[0];
156    T1[1] = T3[1] + T1[1]; T1[0] = T3[0] + T1[0];
157    T2[1] = ror(T1[1], 17) ^ ror(T1[1], 19) ^ (T1[1] >> 10);
158    T2[0] = ror(T1[0], 17) ^ ror(T1[0], 19) ^ (T1[0] >> 10);
159    T3[1] = X[3] + T0[3]; T3[0] = X[2] + T0[2];
160    X[3] = T3[1] + T2[1];
161    X[2] = T3[0] + T2[0];
162    X[1] = T1[1]; X[0] = T1[0];
163
164    store1Reg(output, &X[0]);
165}
166
167void
168Crypto::sha1Op(
169    uint8_t *output,
170    uint8_t *input,
171    uint8_t *input2,
172    SHAOp op)
173{
174    uint32_t X[4], Y[4], Z[4];
175    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
176    _sha1Op(&X[0], &Y[0], &Z[0], op);
177    store1Reg(output, &X[0]);
178}
179
180void
181Crypto::sha1C(
182    uint8_t *output,
183    uint8_t *input,
184    uint8_t *input2)
185{
186    sha1Op(output, input, input2, CHOOSE);
187}
188
189void
190Crypto::sha1P(
191    uint8_t *output,
192    uint8_t *input,
193    uint8_t *input2)
194{
195    sha1Op(output, input, input2, PARITY);
196}
197
198void
199Crypto::sha1M(
200    uint8_t *output,
201    uint8_t *input,
202    uint8_t *input2)
203{
204    sha1Op(output, input, input2, MAJORITY);
205}
206
207void
208Crypto::sha1H(uint8_t *output, uint8_t *input)
209{
210    uint32_t X[4], Y[4];
211    load2Reg(&X[0], &Y[0], output, input);
212    X[0] = ror(Y[0], 2);
213    store1Reg(output, &X[0]);
214}
215
216void
217Crypto::sha1Su0(
218    uint8_t *output,
219    uint8_t *input,
220    uint8_t *input2)
221{
222    uint32_t X[4], Y[4], Z[4], T[4];
223    load3Reg(&X[0], &Y[0], &Z[0], output, input, input2);
224
225    T[3] = Y[1]; T[2] = Y[0]; T[1] = X[3]; T[0] = X[2];
226    X[3] = T[3] ^ X[3] ^ Z[3];
227    X[2] = T[2] ^ X[2] ^ Z[2];
228    X[1] = T[1] ^ X[1] ^ Z[1];
229    X[0] = T[0] ^ X[0] ^ Z[0];
230
231    store1Reg(output, &X[0]);
232}
233
234void
235Crypto::sha1Su1(uint8_t *output, uint8_t *input)
236{
237    uint32_t X[4], Y[4], T[4];
238    load2Reg(&X[0], &Y[0], output, input);
239
240    T[3] = X[3] ^ 0x0;
241    T[2] = X[2] ^ Y[3];
242    T[1] = X[1] ^ Y[2];
243    T[0] = X[0] ^ Y[1];
244    X[2] = ror(T[2], 31); X[1] = ror(T[1], 31); X[0] = ror(T[0], 31);
245    X[3] = ror(T[3], 31) ^ ror(T[0], 30);
246
247    store1Reg(output, &X[0]);
248}
249
250void
251Crypto::load2Reg(
252    uint32_t *X,
253    uint32_t *Y,
254    uint8_t *output,
255    uint8_t *input)
256{
257    for (int i = 0; i < 4; ++i) {
258        X[i] = *((uint32_t *)&output[i*4]);
259        Y[i] = *((uint32_t *)&input[i*4]);
260    }
261}
262
263void
264Crypto::load3Reg(
265    uint32_t *X,
266    uint32_t *Y,
267    uint32_t *Z,
268    uint8_t *output,
269    uint8_t *input,
270    uint8_t *input2)
271{
272    for (int i = 0; i < 4; ++i) {
273        X[i] = *((uint32_t *)&output[i*4]);
274        Y[i] = *((uint32_t *)&input[i*4]);
275        Z[i] = *((uint32_t *)&input2[i*4]);
276    }
277}
278
279void
280Crypto::store1Reg(uint8_t *output, uint32_t *X)
281{
282    for (int i = 0; i < 4; ++i) {
283        output[i*4] = (uint8_t)(X[i]);
284        output[i*4+1] = (uint8_t)(X[i] >> 8);
285        output[i*4+2] = (uint8_t)(X[i] >> 16);
286        output[i*4+3] = (uint8_t)(X[i] >> 24);
287    }
288}
289
290} // namespace ArmISA
291