Merge remote-tracking branch 'remotes/kraxel/tags/pull-console-20141002-1' into staging
[qemu/kevin.git] / target-arm / crypto_helper.c
blobdd60d0b81a4cabcd467b2113902db92b273e6c14
1 /*
2 * crypto_helper.c - emulate v8 Crypto Extensions instructions
4 * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
12 #include <stdlib.h>
14 #include "cpu.h"
15 #include "exec/exec-all.h"
16 #include "exec/helper-proto.h"
17 #include "qemu/aes.h"
19 union CRYPTO_STATE {
20 uint8_t bytes[16];
21 uint32_t words[4];
22 uint64_t l[2];
25 void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
26 uint32_t decrypt)
28 static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox };
29 static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts };
31 union CRYPTO_STATE rk = { .l = {
32 float64_val(env->vfp.regs[rm]),
33 float64_val(env->vfp.regs[rm + 1])
34 } };
35 union CRYPTO_STATE st = { .l = {
36 float64_val(env->vfp.regs[rd]),
37 float64_val(env->vfp.regs[rd + 1])
38 } };
39 int i;
41 assert(decrypt < 2);
43 /* xor state vector with round key */
44 rk.l[0] ^= st.l[0];
45 rk.l[1] ^= st.l[1];
47 /* combine ShiftRows operation and sbox substitution */
48 for (i = 0; i < 16; i++) {
49 st.bytes[i] = sbox[decrypt][rk.bytes[shift[decrypt][i]]];
52 env->vfp.regs[rd] = make_float64(st.l[0]);
53 env->vfp.regs[rd + 1] = make_float64(st.l[1]);
56 void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
57 uint32_t decrypt)
59 static uint32_t const mc[][256] = { {
60 /* MixColumns lookup table */
61 0x00000000, 0x03010102, 0x06020204, 0x05030306,
62 0x0c040408, 0x0f05050a, 0x0a06060c, 0x0907070e,
63 0x18080810, 0x1b090912, 0x1e0a0a14, 0x1d0b0b16,
64 0x140c0c18, 0x170d0d1a, 0x120e0e1c, 0x110f0f1e,
65 0x30101020, 0x33111122, 0x36121224, 0x35131326,
66 0x3c141428, 0x3f15152a, 0x3a16162c, 0x3917172e,
67 0x28181830, 0x2b191932, 0x2e1a1a34, 0x2d1b1b36,
68 0x241c1c38, 0x271d1d3a, 0x221e1e3c, 0x211f1f3e,
69 0x60202040, 0x63212142, 0x66222244, 0x65232346,
70 0x6c242448, 0x6f25254a, 0x6a26264c, 0x6927274e,
71 0x78282850, 0x7b292952, 0x7e2a2a54, 0x7d2b2b56,
72 0x742c2c58, 0x772d2d5a, 0x722e2e5c, 0x712f2f5e,
73 0x50303060, 0x53313162, 0x56323264, 0x55333366,
74 0x5c343468, 0x5f35356a, 0x5a36366c, 0x5937376e,
75 0x48383870, 0x4b393972, 0x4e3a3a74, 0x4d3b3b76,
76 0x443c3c78, 0x473d3d7a, 0x423e3e7c, 0x413f3f7e,
77 0xc0404080, 0xc3414182, 0xc6424284, 0xc5434386,
78 0xcc444488, 0xcf45458a, 0xca46468c, 0xc947478e,
79 0xd8484890, 0xdb494992, 0xde4a4a94, 0xdd4b4b96,
80 0xd44c4c98, 0xd74d4d9a, 0xd24e4e9c, 0xd14f4f9e,
81 0xf05050a0, 0xf35151a2, 0xf65252a4, 0xf55353a6,
82 0xfc5454a8, 0xff5555aa, 0xfa5656ac, 0xf95757ae,
83 0xe85858b0, 0xeb5959b2, 0xee5a5ab4, 0xed5b5bb6,
84 0xe45c5cb8, 0xe75d5dba, 0xe25e5ebc, 0xe15f5fbe,
85 0xa06060c0, 0xa36161c2, 0xa66262c4, 0xa56363c6,
86 0xac6464c8, 0xaf6565ca, 0xaa6666cc, 0xa96767ce,
87 0xb86868d0, 0xbb6969d2, 0xbe6a6ad4, 0xbd6b6bd6,
88 0xb46c6cd8, 0xb76d6dda, 0xb26e6edc, 0xb16f6fde,
89 0x907070e0, 0x937171e2, 0x967272e4, 0x957373e6,
90 0x9c7474e8, 0x9f7575ea, 0x9a7676ec, 0x997777ee,
91 0x887878f0, 0x8b7979f2, 0x8e7a7af4, 0x8d7b7bf6,
92 0x847c7cf8, 0x877d7dfa, 0x827e7efc, 0x817f7ffe,
93 0x9b80801b, 0x98818119, 0x9d82821f, 0x9e83831d,
94 0x97848413, 0x94858511, 0x91868617, 0x92878715,
95 0x8388880b, 0x80898909, 0x858a8a0f, 0x868b8b0d,
96 0x8f8c8c03, 0x8c8d8d01, 0x898e8e07, 0x8a8f8f05,
97 0xab90903b, 0xa8919139, 0xad92923f, 0xae93933d,
98 0xa7949433, 0xa4959531, 0xa1969637, 0xa2979735,
99 0xb398982b, 0xb0999929, 0xb59a9a2f, 0xb69b9b2d,
100 0xbf9c9c23, 0xbc9d9d21, 0xb99e9e27, 0xba9f9f25,
101 0xfba0a05b, 0xf8a1a159, 0xfda2a25f, 0xfea3a35d,
102 0xf7a4a453, 0xf4a5a551, 0xf1a6a657, 0xf2a7a755,
103 0xe3a8a84b, 0xe0a9a949, 0xe5aaaa4f, 0xe6abab4d,
104 0xefacac43, 0xecadad41, 0xe9aeae47, 0xeaafaf45,
105 0xcbb0b07b, 0xc8b1b179, 0xcdb2b27f, 0xceb3b37d,
106 0xc7b4b473, 0xc4b5b571, 0xc1b6b677, 0xc2b7b775,
107 0xd3b8b86b, 0xd0b9b969, 0xd5baba6f, 0xd6bbbb6d,
108 0xdfbcbc63, 0xdcbdbd61, 0xd9bebe67, 0xdabfbf65,
109 0x5bc0c09b, 0x58c1c199, 0x5dc2c29f, 0x5ec3c39d,
110 0x57c4c493, 0x54c5c591, 0x51c6c697, 0x52c7c795,
111 0x43c8c88b, 0x40c9c989, 0x45caca8f, 0x46cbcb8d,
112 0x4fcccc83, 0x4ccdcd81, 0x49cece87, 0x4acfcf85,
113 0x6bd0d0bb, 0x68d1d1b9, 0x6dd2d2bf, 0x6ed3d3bd,
114 0x67d4d4b3, 0x64d5d5b1, 0x61d6d6b7, 0x62d7d7b5,
115 0x73d8d8ab, 0x70d9d9a9, 0x75dadaaf, 0x76dbdbad,
116 0x7fdcdca3, 0x7cdddda1, 0x79dedea7, 0x7adfdfa5,
117 0x3be0e0db, 0x38e1e1d9, 0x3de2e2df, 0x3ee3e3dd,
118 0x37e4e4d3, 0x34e5e5d1, 0x31e6e6d7, 0x32e7e7d5,
119 0x23e8e8cb, 0x20e9e9c9, 0x25eaeacf, 0x26ebebcd,
120 0x2fececc3, 0x2cededc1, 0x29eeeec7, 0x2aefefc5,
121 0x0bf0f0fb, 0x08f1f1f9, 0x0df2f2ff, 0x0ef3f3fd,
122 0x07f4f4f3, 0x04f5f5f1, 0x01f6f6f7, 0x02f7f7f5,
123 0x13f8f8eb, 0x10f9f9e9, 0x15fafaef, 0x16fbfbed,
124 0x1ffcfce3, 0x1cfdfde1, 0x19fefee7, 0x1affffe5,
125 }, {
126 /* Inverse MixColumns lookup table */
127 0x00000000, 0x0b0d090e, 0x161a121c, 0x1d171b12,
128 0x2c342438, 0x27392d36, 0x3a2e3624, 0x31233f2a,
129 0x58684870, 0x5365417e, 0x4e725a6c, 0x457f5362,
130 0x745c6c48, 0x7f516546, 0x62467e54, 0x694b775a,
131 0xb0d090e0, 0xbbdd99ee, 0xa6ca82fc, 0xadc78bf2,
132 0x9ce4b4d8, 0x97e9bdd6, 0x8afea6c4, 0x81f3afca,
133 0xe8b8d890, 0xe3b5d19e, 0xfea2ca8c, 0xf5afc382,
134 0xc48cfca8, 0xcf81f5a6, 0xd296eeb4, 0xd99be7ba,
135 0x7bbb3bdb, 0x70b632d5, 0x6da129c7, 0x66ac20c9,
136 0x578f1fe3, 0x5c8216ed, 0x41950dff, 0x4a9804f1,
137 0x23d373ab, 0x28de7aa5, 0x35c961b7, 0x3ec468b9,
138 0x0fe75793, 0x04ea5e9d, 0x19fd458f, 0x12f04c81,
139 0xcb6bab3b, 0xc066a235, 0xdd71b927, 0xd67cb029,
140 0xe75f8f03, 0xec52860d, 0xf1459d1f, 0xfa489411,
141 0x9303e34b, 0x980eea45, 0x8519f157, 0x8e14f859,
142 0xbf37c773, 0xb43ace7d, 0xa92dd56f, 0xa220dc61,
143 0xf66d76ad, 0xfd607fa3, 0xe07764b1, 0xeb7a6dbf,
144 0xda595295, 0xd1545b9b, 0xcc434089, 0xc74e4987,
145 0xae053edd, 0xa50837d3, 0xb81f2cc1, 0xb31225cf,
146 0x82311ae5, 0x893c13eb, 0x942b08f9, 0x9f2601f7,
147 0x46bde64d, 0x4db0ef43, 0x50a7f451, 0x5baafd5f,
148 0x6a89c275, 0x6184cb7b, 0x7c93d069, 0x779ed967,
149 0x1ed5ae3d, 0x15d8a733, 0x08cfbc21, 0x03c2b52f,
150 0x32e18a05, 0x39ec830b, 0x24fb9819, 0x2ff69117,
151 0x8dd64d76, 0x86db4478, 0x9bcc5f6a, 0x90c15664,
152 0xa1e2694e, 0xaaef6040, 0xb7f87b52, 0xbcf5725c,
153 0xd5be0506, 0xdeb30c08, 0xc3a4171a, 0xc8a91e14,
154 0xf98a213e, 0xf2872830, 0xef903322, 0xe49d3a2c,
155 0x3d06dd96, 0x360bd498, 0x2b1ccf8a, 0x2011c684,
156 0x1132f9ae, 0x1a3ff0a0, 0x0728ebb2, 0x0c25e2bc,
157 0x656e95e6, 0x6e639ce8, 0x737487fa, 0x78798ef4,
158 0x495ab1de, 0x4257b8d0, 0x5f40a3c2, 0x544daacc,
159 0xf7daec41, 0xfcd7e54f, 0xe1c0fe5d, 0xeacdf753,
160 0xdbeec879, 0xd0e3c177, 0xcdf4da65, 0xc6f9d36b,
161 0xafb2a431, 0xa4bfad3f, 0xb9a8b62d, 0xb2a5bf23,
162 0x83868009, 0x888b8907, 0x959c9215, 0x9e919b1b,
163 0x470a7ca1, 0x4c0775af, 0x51106ebd, 0x5a1d67b3,
164 0x6b3e5899, 0x60335197, 0x7d244a85, 0x7629438b,
165 0x1f6234d1, 0x146f3ddf, 0x097826cd, 0x02752fc3,
166 0x335610e9, 0x385b19e7, 0x254c02f5, 0x2e410bfb,
167 0x8c61d79a, 0x876cde94, 0x9a7bc586, 0x9176cc88,
168 0xa055f3a2, 0xab58faac, 0xb64fe1be, 0xbd42e8b0,
169 0xd4099fea, 0xdf0496e4, 0xc2138df6, 0xc91e84f8,
170 0xf83dbbd2, 0xf330b2dc, 0xee27a9ce, 0xe52aa0c0,
171 0x3cb1477a, 0x37bc4e74, 0x2aab5566, 0x21a65c68,
172 0x10856342, 0x1b886a4c, 0x069f715e, 0x0d927850,
173 0x64d90f0a, 0x6fd40604, 0x72c31d16, 0x79ce1418,
174 0x48ed2b32, 0x43e0223c, 0x5ef7392e, 0x55fa3020,
175 0x01b79aec, 0x0aba93e2, 0x17ad88f0, 0x1ca081fe,
176 0x2d83bed4, 0x268eb7da, 0x3b99acc8, 0x3094a5c6,
177 0x59dfd29c, 0x52d2db92, 0x4fc5c080, 0x44c8c98e,
178 0x75ebf6a4, 0x7ee6ffaa, 0x63f1e4b8, 0x68fcedb6,
179 0xb1670a0c, 0xba6a0302, 0xa77d1810, 0xac70111e,
180 0x9d532e34, 0x965e273a, 0x8b493c28, 0x80443526,
181 0xe90f427c, 0xe2024b72, 0xff155060, 0xf418596e,
182 0xc53b6644, 0xce366f4a, 0xd3217458, 0xd82c7d56,
183 0x7a0ca137, 0x7101a839, 0x6c16b32b, 0x671bba25,
184 0x5638850f, 0x5d358c01, 0x40229713, 0x4b2f9e1d,
185 0x2264e947, 0x2969e049, 0x347efb5b, 0x3f73f255,
186 0x0e50cd7f, 0x055dc471, 0x184adf63, 0x1347d66d,
187 0xcadc31d7, 0xc1d138d9, 0xdcc623cb, 0xd7cb2ac5,
188 0xe6e815ef, 0xede51ce1, 0xf0f207f3, 0xfbff0efd,
189 0x92b479a7, 0x99b970a9, 0x84ae6bbb, 0x8fa362b5,
190 0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d,
191 } };
192 union CRYPTO_STATE st = { .l = {
193 float64_val(env->vfp.regs[rm]),
194 float64_val(env->vfp.regs[rm + 1])
195 } };
196 int i;
198 assert(decrypt < 2);
200 for (i = 0; i < 16; i += 4) {
201 st.words[i >> 2] = cpu_to_le32(
202 mc[decrypt][st.bytes[i]] ^
203 rol32(mc[decrypt][st.bytes[i + 1]], 8) ^
204 rol32(mc[decrypt][st.bytes[i + 2]], 16) ^
205 rol32(mc[decrypt][st.bytes[i + 3]], 24));
208 env->vfp.regs[rd] = make_float64(st.l[0]);
209 env->vfp.regs[rd + 1] = make_float64(st.l[1]);
213 * SHA-1 logical functions
216 static uint32_t cho(uint32_t x, uint32_t y, uint32_t z)
218 return (x & (y ^ z)) ^ z;
221 static uint32_t par(uint32_t x, uint32_t y, uint32_t z)
223 return x ^ y ^ z;
226 static uint32_t maj(uint32_t x, uint32_t y, uint32_t z)
228 return (x & y) | ((x | y) & z);
231 void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn,
232 uint32_t rm, uint32_t op)
234 union CRYPTO_STATE d = { .l = {
235 float64_val(env->vfp.regs[rd]),
236 float64_val(env->vfp.regs[rd + 1])
237 } };
238 union CRYPTO_STATE n = { .l = {
239 float64_val(env->vfp.regs[rn]),
240 float64_val(env->vfp.regs[rn + 1])
241 } };
242 union CRYPTO_STATE m = { .l = {
243 float64_val(env->vfp.regs[rm]),
244 float64_val(env->vfp.regs[rm + 1])
245 } };
247 if (op == 3) { /* sha1su0 */
248 d.l[0] ^= d.l[1] ^ m.l[0];
249 d.l[1] ^= n.l[0] ^ m.l[1];
250 } else {
251 int i;
253 for (i = 0; i < 4; i++) {
254 uint32_t t;
256 switch (op) {
257 case 0: /* sha1c */
258 t = cho(d.words[1], d.words[2], d.words[3]);
259 break;
260 case 1: /* sha1p */
261 t = par(d.words[1], d.words[2], d.words[3]);
262 break;
263 case 2: /* sha1m */
264 t = maj(d.words[1], d.words[2], d.words[3]);
265 break;
266 default:
267 g_assert_not_reached();
269 t += rol32(d.words[0], 5) + n.words[0] + m.words[i];
271 n.words[0] = d.words[3];
272 d.words[3] = d.words[2];
273 d.words[2] = ror32(d.words[1], 2);
274 d.words[1] = d.words[0];
275 d.words[0] = t;
278 env->vfp.regs[rd] = make_float64(d.l[0]);
279 env->vfp.regs[rd + 1] = make_float64(d.l[1]);
282 void HELPER(crypto_sha1h)(CPUARMState *env, uint32_t rd, uint32_t rm)
284 union CRYPTO_STATE m = { .l = {
285 float64_val(env->vfp.regs[rm]),
286 float64_val(env->vfp.regs[rm + 1])
287 } };
289 m.words[0] = ror32(m.words[0], 2);
290 m.words[1] = m.words[2] = m.words[3] = 0;
292 env->vfp.regs[rd] = make_float64(m.l[0]);
293 env->vfp.regs[rd + 1] = make_float64(m.l[1]);
296 void HELPER(crypto_sha1su1)(CPUARMState *env, uint32_t rd, uint32_t rm)
298 union CRYPTO_STATE d = { .l = {
299 float64_val(env->vfp.regs[rd]),
300 float64_val(env->vfp.regs[rd + 1])
301 } };
302 union CRYPTO_STATE m = { .l = {
303 float64_val(env->vfp.regs[rm]),
304 float64_val(env->vfp.regs[rm + 1])
305 } };
307 d.words[0] = rol32(d.words[0] ^ m.words[1], 1);
308 d.words[1] = rol32(d.words[1] ^ m.words[2], 1);
309 d.words[2] = rol32(d.words[2] ^ m.words[3], 1);
310 d.words[3] = rol32(d.words[3] ^ d.words[0], 1);
312 env->vfp.regs[rd] = make_float64(d.l[0]);
313 env->vfp.regs[rd + 1] = make_float64(d.l[1]);
317 * The SHA-256 logical functions, according to
318 * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
321 static uint32_t S0(uint32_t x)
323 return ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22);
326 static uint32_t S1(uint32_t x)
328 return ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25);
331 static uint32_t s0(uint32_t x)
333 return ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3);
336 static uint32_t s1(uint32_t x)
338 return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
341 void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn,
342 uint32_t rm)
344 union CRYPTO_STATE d = { .l = {
345 float64_val(env->vfp.regs[rd]),
346 float64_val(env->vfp.regs[rd + 1])
347 } };
348 union CRYPTO_STATE n = { .l = {
349 float64_val(env->vfp.regs[rn]),
350 float64_val(env->vfp.regs[rn + 1])
351 } };
352 union CRYPTO_STATE m = { .l = {
353 float64_val(env->vfp.regs[rm]),
354 float64_val(env->vfp.regs[rm + 1])
355 } };
356 int i;
358 for (i = 0; i < 4; i++) {
359 uint32_t t = cho(n.words[0], n.words[1], n.words[2]) + n.words[3]
360 + S1(n.words[0]) + m.words[i];
362 n.words[3] = n.words[2];
363 n.words[2] = n.words[1];
364 n.words[1] = n.words[0];
365 n.words[0] = d.words[3] + t;
367 t += maj(d.words[0], d.words[1], d.words[2]) + S0(d.words[0]);
369 d.words[3] = d.words[2];
370 d.words[2] = d.words[1];
371 d.words[1] = d.words[0];
372 d.words[0] = t;
375 env->vfp.regs[rd] = make_float64(d.l[0]);
376 env->vfp.regs[rd + 1] = make_float64(d.l[1]);
379 void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn,
380 uint32_t rm)
382 union CRYPTO_STATE d = { .l = {
383 float64_val(env->vfp.regs[rd]),
384 float64_val(env->vfp.regs[rd + 1])
385 } };
386 union CRYPTO_STATE n = { .l = {
387 float64_val(env->vfp.regs[rn]),
388 float64_val(env->vfp.regs[rn + 1])
389 } };
390 union CRYPTO_STATE m = { .l = {
391 float64_val(env->vfp.regs[rm]),
392 float64_val(env->vfp.regs[rm + 1])
393 } };
394 int i;
396 for (i = 0; i < 4; i++) {
397 uint32_t t = cho(d.words[0], d.words[1], d.words[2]) + d.words[3]
398 + S1(d.words[0]) + m.words[i];
400 d.words[3] = d.words[2];
401 d.words[2] = d.words[1];
402 d.words[1] = d.words[0];
403 d.words[0] = n.words[3 - i] + t;
406 env->vfp.regs[rd] = make_float64(d.l[0]);
407 env->vfp.regs[rd + 1] = make_float64(d.l[1]);
410 void HELPER(crypto_sha256su0)(CPUARMState *env, uint32_t rd, uint32_t rm)
412 union CRYPTO_STATE d = { .l = {
413 float64_val(env->vfp.regs[rd]),
414 float64_val(env->vfp.regs[rd + 1])
415 } };
416 union CRYPTO_STATE m = { .l = {
417 float64_val(env->vfp.regs[rm]),
418 float64_val(env->vfp.regs[rm + 1])
419 } };
421 d.words[0] += s0(d.words[1]);
422 d.words[1] += s0(d.words[2]);
423 d.words[2] += s0(d.words[3]);
424 d.words[3] += s0(m.words[0]);
426 env->vfp.regs[rd] = make_float64(d.l[0]);
427 env->vfp.regs[rd + 1] = make_float64(d.l[1]);
430 void HELPER(crypto_sha256su1)(CPUARMState *env, uint32_t rd, uint32_t rn,
431 uint32_t rm)
433 union CRYPTO_STATE d = { .l = {
434 float64_val(env->vfp.regs[rd]),
435 float64_val(env->vfp.regs[rd + 1])
436 } };
437 union CRYPTO_STATE n = { .l = {
438 float64_val(env->vfp.regs[rn]),
439 float64_val(env->vfp.regs[rn + 1])
440 } };
441 union CRYPTO_STATE m = { .l = {
442 float64_val(env->vfp.regs[rm]),
443 float64_val(env->vfp.regs[rm + 1])
444 } };
446 d.words[0] += s1(m.words[2]) + n.words[1];
447 d.words[1] += s1(m.words[3]) + n.words[2];
448 d.words[2] += s1(d.words[0]) + n.words[3];
449 d.words[3] += s1(d.words[1]) + m.words[0];
451 env->vfp.regs[rd] = make_float64(d.l[0]);
452 env->vfp.regs[rd + 1] = make_float64(d.l[1]);