]> Git Repo - qemu.git/blob - target-arm/crypto_helper.c
block/raw-posix: Fix disk corruption in try_fiemap
[qemu.git] / target-arm / crypto_helper.c
1 /*
2  * crypto_helper.c - emulate v8 Crypto Extensions instructions
3  *
4  * Copyright (C) 2013 - 2014 Linaro Ltd <[email protected]>
5  *
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.
10  */
11
12 #include <stdlib.h>
13
14 #include "cpu.h"
15 #include "exec/exec-all.h"
16 #include "exec/helper-proto.h"
17 #include "qemu/aes.h"
18
19 union CRYPTO_STATE {
20     uint8_t    bytes[16];
21     uint32_t   words[4];
22     uint64_t   l[2];
23 };
24
25 void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
26                          uint32_t decrypt)
27 {
28     static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox };
29     static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts };
30
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;
40
41     assert(decrypt < 2);
42
43     /* xor state vector with round key */
44     rk.l[0] ^= st.l[0];
45     rk.l[1] ^= st.l[1];
46
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]]];
50     }
51
52     env->vfp.regs[rd] = make_float64(st.l[0]);
53     env->vfp.regs[rd + 1] = make_float64(st.l[1]);
54 }
55
56 void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
57                           uint32_t decrypt)
58 {
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;
197
198     assert(decrypt < 2);
199
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));
206     }
207
208     env->vfp.regs[rd] = make_float64(st.l[0]);
209     env->vfp.regs[rd + 1] = make_float64(st.l[1]);
210 }
211
212 /*
213  * SHA-1 logical functions
214  */
215
216 static uint32_t cho(uint32_t x, uint32_t y, uint32_t z)
217 {
218     return (x & (y ^ z)) ^ z;
219 }
220
221 static uint32_t par(uint32_t x, uint32_t y, uint32_t z)
222 {
223     return x ^ y ^ z;
224 }
225
226 static uint32_t maj(uint32_t x, uint32_t y, uint32_t z)
227 {
228     return (x & y) | ((x | y) & z);
229 }
230
231 void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn,
232                               uint32_t rm, uint32_t op)
233 {
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     } };
246
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;
252
253         for (i = 0; i < 4; i++) {
254             uint32_t t;
255
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();
268             }
269             t += rol32(d.words[0], 5) + n.words[0] + m.words[i];
270
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;
276         }
277     }
278     env->vfp.regs[rd] = make_float64(d.l[0]);
279     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
280 }
281
282 void HELPER(crypto_sha1h)(CPUARMState *env, uint32_t rd, uint32_t rm)
283 {
284     union CRYPTO_STATE m = { .l = {
285         float64_val(env->vfp.regs[rm]),
286         float64_val(env->vfp.regs[rm + 1])
287     } };
288
289     m.words[0] = ror32(m.words[0], 2);
290     m.words[1] = m.words[2] = m.words[3] = 0;
291
292     env->vfp.regs[rd] = make_float64(m.l[0]);
293     env->vfp.regs[rd + 1] = make_float64(m.l[1]);
294 }
295
296 void HELPER(crypto_sha1su1)(CPUARMState *env, uint32_t rd, uint32_t rm)
297 {
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     } };
306
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);
311
312     env->vfp.regs[rd] = make_float64(d.l[0]);
313     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
314 }
315
316 /*
317  * The SHA-256 logical functions, according to
318  * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
319  */
320
321 static uint32_t S0(uint32_t x)
322 {
323     return ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22);
324 }
325
326 static uint32_t S1(uint32_t x)
327 {
328     return ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25);
329 }
330
331 static uint32_t s0(uint32_t x)
332 {
333     return ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3);
334 }
335
336 static uint32_t s1(uint32_t x)
337 {
338     return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
339 }
340
341 void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn,
342                             uint32_t rm)
343 {
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;
357
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];
361
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;
366
367         t += maj(d.words[0], d.words[1], d.words[2]) + S0(d.words[0]);
368
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;
373     }
374
375     env->vfp.regs[rd] = make_float64(d.l[0]);
376     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
377 }
378
379 void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn,
380                              uint32_t rm)
381 {
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;
395
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];
399
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;
404     }
405
406     env->vfp.regs[rd] = make_float64(d.l[0]);
407     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
408 }
409
410 void HELPER(crypto_sha256su0)(CPUARMState *env, uint32_t rd, uint32_t rm)
411 {
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     } };
420
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]);
425
426     env->vfp.regs[rd] = make_float64(d.l[0]);
427     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
428 }
429
430 void HELPER(crypto_sha256su1)(CPUARMState *env, uint32_t rd, uint32_t rn,
431                               uint32_t rm)
432 {
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     } };
445
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];
450
451     env->vfp.regs[rd] = make_float64(d.l[0]);
452     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
453 }
This page took 0.050223 seconds and 4 git commands to generate.