source: trunk/library/camellia.c @ 1238

Revision 1238, 32.7 KB checked in by paul, 4 weeks ago (diff)
  • Small code rewrite
Line 
1/*
2 *  Camellia implementation
3 *
4 *  Copyright (C) 2006-2010, Brainspark B.V.
5 *
6 *  This file is part of PolarSSL (http://www.polarssl.org)
7 *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 *  All rights reserved.
10 *
11 *  This program is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License as published by
13 *  the Free Software Foundation; either version 2 of the License, or
14 *  (at your option) any later version.
15 *
16 *  This program is distributed in the hope that it will be useful,
17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 *  GNU General Public License for more details.
20 *
21 *  You should have received a copy of the GNU General Public License along
22 *  with this program; if not, write to the Free Software Foundation, Inc.,
23 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25/*
26 *  The Camellia block cipher was designed by NTT and Mitsubishi Electric
27 *  Corporation.
28 *
29 *  http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf
30 */
31
32#include "polarssl/config.h"
33
34#if defined(POLARSSL_CAMELLIA_C)
35
36#include "polarssl/camellia.h"
37
38/*
39 * 32-bit integer manipulation macros (big endian)
40 */
41#ifndef GET_ULONG_BE
42#define GET_ULONG_BE(n,b,i)                             \
43{                                                       \
44    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
45        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
46        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
47        | ( (unsigned long) (b)[(i) + 3]       );       \
48}
49#endif
50
51#ifndef PUT_ULONG_BE
52#define PUT_ULONG_BE(n,b,i)                             \
53{                                                       \
54    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
55    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
56    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
57    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
58}
59#endif
60
61static const unsigned char SIGMA_CHARS[6][8] =
62{
63    { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
64    { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 },
65    { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe },
66    { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c },
67    { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d },
68    { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd }
69};
70
71#if defined(POLARSSL_CAMELLIA_SMALL_MEMORY)
72
73static const unsigned char FSb[256] =
74{
75    112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65,
76     35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189,
77    134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26,
78    166,225, 57,202,213, 71, 93, 61,217,  1, 90,214, 81, 86,108, 77,
79    139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153,
80    223, 76,203,194, 52,126,118,  5,109,183,169, 49,209, 23,  4,215,
81     20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34,
82    254, 68,207,178,195,181,122,145, 36,  8,232,168, 96,252,105, 80,
83    170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210,
84     16,196,  0, 72,163,247,117,219,138,  3,230,218,  9, 63,221,148,
85    135, 92,131,  2,205, 74,144, 51,115,103,246,243,157,127,191,226,
86     82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46,
87    233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89,
88    120,152,  6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250,
89    114,  7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164,
90     64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158
91};
92
93#define SBOX1(n) FSb[(n)]
94#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)
95#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
96#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]
97
98#else
99
100static const unsigned char FSb[256] =
101{
102    112, 130,  44, 236, 179,  39, 192, 229, 228, 133,  87,  53, 234,  12, 174,  65,
103    35, 239, 107, 147,  69,  25, 165,  33, 237,  14,  79,  78,  29, 101, 146, 189,
104    134, 184, 175, 143, 124, 235,  31, 206,  62,  48, 220,  95,  94, 197,  11,  26,
105    166, 225,  57, 202, 213,  71,  93,  61, 217,   1,  90, 214,  81,  86, 108,  77,
106    139,  13, 154, 102, 251, 204, 176,  45, 116,  18,  43,  32, 240, 177, 132, 153,
107    223,  76, 203, 194,  52, 126, 118,   5, 109, 183, 169,  49, 209,  23,   4, 215,
108    20,  88,  58,  97, 222,  27,  17,  28,  50,  15, 156,  22,  83,  24, 242,  34,
109    254,  68, 207, 178, 195, 181, 122, 145,  36,   8, 232, 168,  96, 252, 105,  80,
110    170, 208, 160, 125, 161, 137,  98, 151,  84,  91,  30, 149, 224, 255, 100, 210,
111    16, 196,   0,  72, 163, 247, 117, 219, 138,   3, 230, 218,   9,  63, 221, 148,
112    135,  92, 131,   2, 205,  74, 144,  51, 115, 103, 246, 243, 157, 127, 191, 226,
113    82, 155, 216,  38, 200,  55, 198,  59, 129, 150, 111,  75,  19, 190,  99,  46,
114    233, 121, 167, 140, 159, 110, 188, 142,  41, 245, 249, 182,  47, 253, 180,  89,
115    120, 152,   6, 106, 231,  70, 113, 186, 212,  37, 171,  66, 136, 162, 141, 250,
116    114,   7, 185,  85, 248, 238, 172,  10,  54,  73,  42, 104,  60,  56, 241, 164,
117    64,  40, 211, 123, 187, 201,  67, 193,  21, 227, 173, 244, 119, 199, 128, 158
118};
119
120static const unsigned char FSb2[256] =
121{
122    224,   5,  88, 217, 103,  78, 129, 203, 201,  11, 174, 106, 213,  24,  93, 130,
123    70, 223, 214,  39, 138,  50,  75,  66, 219,  28, 158, 156,  58, 202,  37, 123,
124    13, 113,  95,  31, 248, 215,  62, 157, 124,  96, 185, 190, 188, 139,  22,  52,
125    77, 195, 114, 149, 171, 142, 186, 122, 179,   2, 180, 173, 162, 172, 216, 154,
126    23,  26,  53, 204, 247, 153,  97,  90, 232,  36,  86,  64, 225,  99,   9,  51,
127    191, 152, 151, 133, 104, 252, 236,  10, 218, 111,  83,  98, 163,  46,   8, 175,
128    40, 176, 116, 194, 189,  54,  34,  56, 100,  30,  57,  44, 166,  48, 229,  68,
129    253, 136, 159, 101, 135, 107, 244,  35,  72,  16, 209,  81, 192, 249, 210, 160,
130    85, 161,  65, 250,  67,  19, 196,  47, 168, 182,  60,  43, 193, 255, 200, 165,
131    32, 137,   0, 144,  71, 239, 234, 183,  21,   6, 205, 181,  18, 126, 187,  41,
132    15, 184,   7,   4, 155, 148,  33, 102, 230, 206, 237, 231,  59, 254, 127, 197,
133    164,  55, 177,  76, 145, 110, 141, 118,   3,  45, 222, 150,  38, 125, 198,  92,
134    211, 242,  79,  25,  63, 220, 121,  29,  82, 235, 243, 109,  94, 251, 105, 178,
135    240,  49,  12, 212, 207, 140, 226, 117, 169,  74,  87, 132,  17,  69,  27, 245,
136    228,  14, 115, 170, 241, 221,  89,  20, 108, 146,  84, 208, 120, 112, 227,  73,
137    128,  80, 167, 246, 119, 147, 134, 131,  42, 199,  91, 233, 238, 143,   1,  61
138};
139
140static const unsigned char FSb3[256] =
141{
142    56,  65,  22, 118, 217, 147,  96, 242, 114, 194, 171, 154, 117,   6,  87, 160,
143    145, 247, 181, 201, 162, 140, 210, 144, 246,   7, 167,  39, 142, 178,  73, 222,
144    67,  92, 215, 199,  62, 245, 143, 103,  31,  24, 110, 175,  47, 226, 133,  13,
145    83, 240, 156, 101, 234, 163, 174, 158, 236, 128,  45, 107, 168,  43,  54, 166,
146    197, 134,  77,  51, 253, 102,  88, 150,  58,   9, 149,  16, 120, 216,  66, 204,
147    239,  38, 229,  97,  26,  63,  59, 130, 182, 219, 212, 152, 232, 139,   2, 235,
148    10,  44,  29, 176, 111, 141, 136,  14,  25, 135,  78,  11, 169,  12, 121,  17,
149    127,  34, 231,  89, 225, 218,  61, 200,  18,   4, 116,  84,  48, 126, 180,  40,
150    85, 104,  80, 190, 208, 196,  49, 203,  42, 173,  15, 202, 112, 255,  50, 105,
151    8,  98,   0,  36, 209, 251, 186, 237,  69, 129, 115, 109, 132, 159, 238,  74,
152    195,  46, 193,   1, 230,  37,  72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
153    41, 205, 108,  19, 100, 155,  99, 157, 192,  75, 183, 165, 137,  95, 177,  23,
154    244, 188, 211,  70, 207,  55,  94,  71, 148, 250, 252,  91, 151, 254,  90, 172,
155    60,  76,   3,  53, 243,  35, 184,  93, 106, 146, 213,  33,  68,  81, 198, 125,
156    57, 131, 220, 170, 124, 119,  86,   5,  27, 164,  21,  52,  30,  28, 248,  82,
157    32,  20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227,  64,  79
158};
159
160static const unsigned char FSb4[256] =
161{
162    112,  44, 179, 192, 228,  87, 234, 174,  35, 107,  69, 165, 237,  79,  29, 146,
163    134, 175, 124,  31,  62, 220,  94,  11, 166,  57, 213,  93, 217,  90,  81, 108,
164    139, 154, 251, 176, 116,  43, 240, 132, 223, 203,  52, 118, 109, 169, 209,   4,
165    20,  58, 222,  17,  50, 156,  83, 242, 254, 207, 195, 122,  36, 232,  96, 105,
166    170, 160, 161,  98,  84,  30, 224, 100,  16,   0, 163, 117, 138, 230,   9, 221,
167    135, 131, 205, 144, 115, 246, 157, 191,  82, 216, 200, 198, 129, 111,  19,  99,
168    233, 167, 159, 188,  41, 249,  47, 180, 120,   6, 231, 113, 212, 171, 136, 141,
169    114, 185, 248, 172,  54,  42,  60, 241,  64, 211, 187,  67,  21, 173, 119, 128,
170    130, 236,  39, 229, 133,  53,  12,  65, 239, 147,  25,  33,  14,  78, 101, 189,
171    184, 143, 235, 206,  48,  95, 197,  26, 225, 202,  71,  61,   1, 214,  86,  77,
172    13, 102, 204,  45,  18,  32, 177, 153,  76, 194, 126,   5, 183,  49,  23, 215,
173    88,  97,  27,  28,  15,  22,  24,  34,  68, 178, 181, 145,   8, 168, 252,  80,
174    208, 125, 137, 151,  91, 149, 255, 210, 196,  72, 247, 219,   3, 218,  63, 148,
175    92,   2,  74,  51, 103, 243, 127, 226, 155,  38,  55,  59, 150,  75, 190,  46,
176    121, 140, 110, 142, 245, 182, 253,  89, 152, 106,  70, 186,  37,  66, 162, 250,
177    7,  85, 238,  10,  73, 104,  56, 164,  40, 123, 201, 193, 227, 244, 199, 158
178};
179
180#define SBOX1(n) FSb[(n)]
181#define SBOX2(n) FSb2[(n)]
182#define SBOX3(n) FSb3[(n)]
183#define SBOX4(n) FSb4[(n)]
184
185#endif
186
187static const unsigned char shifts[2][4][4] =
188{
189    {
190        { 1, 1, 1, 1 }, /* KL */
191        { 0, 0, 0, 0 }, /* KR */
192        { 1, 1, 1, 1 }, /* KA */
193        { 0, 0, 0, 0 }  /* KB */
194    },
195    {
196        { 1, 0, 1, 1 }, /* KL */
197        { 1, 1, 0, 1 }, /* KR */
198        { 1, 1, 1, 0 }, /* KA */
199        { 1, 1, 0, 1 }  /* KB */
200    }
201};
202
203static const signed char indexes[2][4][20] =
204{
205    {
206        {  0,  1,  2,  3,  8,  9, 10, 11, 38, 39,
207          36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */
208        { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
209          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */
210        {  4,  5,  6,  7, 12, 13, 14, 15, 16, 17,
211          18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */
212        { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
213          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }  /* KB -> RK */
214    },
215    {
216        {  0,  1,  2,  3, 61, 62, 63, 60, -1, -1,
217          -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */
218        { -1, -1, -1, -1,  8,  9, 10, 11, 16, 17,
219          18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */
220        { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59,
221          56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */
222        {  4,  5,  6,  7, 65, 66, 67, 64, 20, 21,
223          22, 23, -1, -1, -1, -1, 43, 40, 41, 42 }  /* KB -> RK */
224    }
225};
226
227static const signed char transposes[2][20] =
228{
229    {
230        21, 22, 23, 20,
231        -1, -1, -1, -1,
232        18, 19, 16, 17,
233        11,  8,  9, 10,
234        15, 12, 13, 14
235    },
236    {
237        25, 26, 27, 24,
238        29, 30, 31, 28,
239        18, 19, 16, 17,
240        -1, -1, -1, -1,
241        -1, -1, -1, -1
242    }
243};
244
245/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */
246#define ROTL(DEST, SRC, SHIFT)                                      \
247{                                                                   \
248    (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT));   \
249    (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT));   \
250    (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT));   \
251    (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT));   \
252}
253
254#define FL(XL, XR, KL, KR)                                          \
255{                                                                   \
256    (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR);   \
257    (XL) = ((XR) | (KR)) ^ (XL);                                    \
258}
259   
260#define FLInv(YL, YR, KL, KR)                                       \
261{                                                                   \
262    (YL) = ((YR) | (KR)) ^ (YL);                                    \
263    (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR);   \
264}
265   
266#define SHIFT_AND_PLACE(INDEX, OFFSET)                      \
267{                                                           \
268    TK[0] = KC[(OFFSET) * 4 + 0];                           \
269    TK[1] = KC[(OFFSET) * 4 + 1];                           \
270    TK[2] = KC[(OFFSET) * 4 + 2];                           \
271    TK[3] = KC[(OFFSET) * 4 + 3];                           \
272                                                            \
273    for ( i = 1; i <= 4; i++ )                              \
274        if (shifts[(INDEX)][(OFFSET)][i -1])                \
275            ROTL(TK + i * 4, TK, (15 * i) % 32);            \
276                                                            \
277    for ( i = 0; i < 20; i++ )                              \
278        if (indexes[(INDEX)][(OFFSET)][i] != -1) {          \
279        RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ];        \
280    }                                                       \
281}
282
283static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t z[2])
284{
285    uint32_t I0, I1;
286    I0 = x[0] ^ k[0];
287    I1 = x[1] ^ k[1];
288
289    I0 = (SBOX1((I0 >> 24) & 0xFF) << 24) |
290         (SBOX2((I0 >> 16) & 0xFF) << 16) |
291         (SBOX3((I0 >>  8) & 0xFF) <<  8) |
292         (SBOX4((I0      ) & 0xFF)      );
293    I1 = (SBOX2((I1 >> 24) & 0xFF) << 24) |
294         (SBOX3((I1 >> 16) & 0xFF) << 16) |
295         (SBOX4((I1 >>  8) & 0xFF) <<  8) |
296         (SBOX1((I1      ) & 0xFF)      );
297
298    I0 ^= (I1 << 8) | (I1 >> 24);
299    I1 ^= (I0 << 16) | (I0 >> 16);
300    I0 ^= (I1 >> 8) | (I1 << 24);
301    I1 ^= (I0 >> 8) | (I0 << 24);
302
303    z[0] ^= I1;
304    z[1] ^= I0;
305}
306
307/*
308 * Camellia key schedule (encryption)
309 */
310int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
311{
312    int idx;
313    size_t i;
314    uint32_t *RK;
315    unsigned char t[64];
316    uint32_t SIGMA[6][2];
317    uint32_t KC[16];
318    uint32_t TK[20];
319
320    RK = ctx->rk;
321
322    memset(t, 0, 64);
323    memset(RK, 0, sizeof(ctx->rk));
324
325    switch( keysize )
326    {
327        case 128: ctx->nr = 3; idx = 0; break;
328        case 192:
329        case 256: ctx->nr = 4; idx = 1; break;
330        default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
331    }
332
333    for( i = 0; i < keysize / 8; ++i)
334        t[i] = key[i];
335
336    if (keysize == 192) {
337        for (i = 0; i < 8; i++)
338            t[24 + i] = ~t[16 + i];
339    }
340
341    /*
342     * Prepare SIGMA values
343     */
344    for (i = 0; i < 6; i++) {
345        GET_ULONG_BE(SIGMA[i][0], SIGMA_CHARS[i], 0);
346        GET_ULONG_BE(SIGMA[i][1], SIGMA_CHARS[i], 4);
347    }
348
349    /*
350     * Key storage in KC
351     * Order: KL, KR, KA, KB
352     */
353    memset(KC, 0, sizeof(KC));
354
355    /* Store KL, KR */
356    for (i = 0; i < 8; i++)
357        GET_ULONG_BE(KC[i], t, i * 4);
358
359    /* Generate KA */
360    for( i = 0; i < 4; ++i)
361        KC[8 + i] = KC[i] ^ KC[4 + i];
362
363    camellia_feistel(KC + 8, SIGMA[0], KC + 10);
364    camellia_feistel(KC + 10, SIGMA[1], KC + 8);
365
366    for( i = 0; i < 4; ++i)
367        KC[8 + i] ^= KC[i];
368
369    camellia_feistel(KC + 8, SIGMA[2], KC + 10);
370    camellia_feistel(KC + 10, SIGMA[3], KC + 8);
371
372    if (keysize > 128) {
373        /* Generate KB */
374        for( i = 0; i < 4; ++i)
375            KC[12 + i] = KC[4 + i] ^ KC[8 + i];
376
377        camellia_feistel(KC + 12, SIGMA[4], KC + 14);
378        camellia_feistel(KC + 14, SIGMA[5], KC + 12);
379    }
380
381    /*
382     * Generating subkeys
383     */ 
384
385    /* Manipulating KL */
386    SHIFT_AND_PLACE(idx, 0);
387
388    /* Manipulating KR */
389    if (keysize > 128) {
390        SHIFT_AND_PLACE(idx, 1);
391    }
392
393    /* Manipulating KA */
394    SHIFT_AND_PLACE(idx, 2);
395
396    /* Manipulating KB */
397    if (keysize > 128) {
398        SHIFT_AND_PLACE(idx, 3);
399    }
400
401    /* Do transpositions */
402    for ( i = 0; i < 20; i++ ) {
403        if (transposes[idx][i] != -1) {
404            RK[32 + 12 * idx + i] = RK[transposes[idx][i]];
405        }
406    }
407
408    return( 0 );
409}
410
411/*
412 * Camellia key schedule (decryption)
413 */
414int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
415{
416    int idx;
417    size_t i;
418    camellia_context cty;
419    uint32_t *RK;
420    uint32_t *SK;
421    int ret;
422
423    switch( keysize )
424    {
425        case 128: ctx->nr = 3; idx = 0; break;
426        case 192:
427        case 256: ctx->nr = 4; idx = 1; break;
428        default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
429    }
430
431    RK = ctx->rk;
432
433    ret = camellia_setkey_enc(&cty, key, keysize);
434    if( ret != 0 )
435        return( ret );
436
437    SK = cty.rk + 24 * 2 + 8 * idx * 2;
438
439    *RK++ = *SK++;
440    *RK++ = *SK++;
441    *RK++ = *SK++;
442    *RK++ = *SK++;
443
444    for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4)
445    {
446        *RK++ = *SK++;
447        *RK++ = *SK++;
448    }
449
450    SK -= 2;
451
452    *RK++ = *SK++;
453    *RK++ = *SK++;
454    *RK++ = *SK++;
455    *RK++ = *SK++;
456
457    memset( &cty, 0, sizeof( camellia_context ) );
458
459    return( 0 );
460}
461
462/*
463 * Camellia-ECB block encryption/decryption
464 */
465int camellia_crypt_ecb( camellia_context *ctx,
466                    int mode,
467                    const unsigned char input[16],
468                    unsigned char output[16] )
469{
470    int NR;
471    uint32_t *RK, X[4];
472
473    ( (void) mode );
474
475    NR = ctx->nr;
476    RK = ctx->rk;
477
478    GET_ULONG_BE( X[0], input,  0 );
479    GET_ULONG_BE( X[1], input,  4 );
480    GET_ULONG_BE( X[2], input,  8 );
481    GET_ULONG_BE( X[3], input, 12 );
482
483    X[0] ^= *RK++;
484    X[1] ^= *RK++;
485    X[2] ^= *RK++;
486    X[3] ^= *RK++;
487
488    while (NR) {
489        --NR;
490        camellia_feistel(X, RK, X + 2);
491        RK += 2;
492        camellia_feistel(X + 2, RK, X);
493        RK += 2;
494        camellia_feistel(X, RK, X + 2);
495        RK += 2;
496        camellia_feistel(X + 2, RK, X);
497        RK += 2;
498        camellia_feistel(X, RK, X + 2);
499        RK += 2;
500        camellia_feistel(X + 2, RK, X);
501        RK += 2;
502
503        if (NR) {
504            FL(X[0], X[1], RK[0], RK[1]);
505            RK += 2;
506            FLInv(X[2], X[3], RK[0], RK[1]);
507            RK += 2;
508        }
509    }
510
511    X[2] ^= *RK++;
512    X[3] ^= *RK++;
513    X[0] ^= *RK++;
514    X[1] ^= *RK++;
515
516    PUT_ULONG_BE( X[2], output,  0 );
517    PUT_ULONG_BE( X[3], output,  4 );
518    PUT_ULONG_BE( X[0], output,  8 );
519    PUT_ULONG_BE( X[1], output, 12 );
520
521    return( 0 );
522}
523
524/*
525 * Camellia-CBC buffer encryption/decryption
526 */
527int camellia_crypt_cbc( camellia_context *ctx,
528                    int mode,
529                    size_t length,
530                    unsigned char iv[16],
531                    const unsigned char *input,
532                    unsigned char *output )
533{
534    int i;
535    unsigned char temp[16];
536
537    if( length % 16 )
538        return( POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
539
540    if( mode == CAMELLIA_DECRYPT )
541    {
542        while( length > 0 )
543        {
544            memcpy( temp, input, 16 );
545            camellia_crypt_ecb( ctx, mode, input, output );
546
547            for( i = 0; i < 16; i++ )
548                output[i] = (unsigned char)( output[i] ^ iv[i] );
549
550            memcpy( iv, temp, 16 );
551
552            input  += 16;
553            output += 16;
554            length -= 16;
555        }
556    }
557    else
558    {
559        while( length > 0 )
560        {
561            for( i = 0; i < 16; i++ )
562                output[i] = (unsigned char)( input[i] ^ iv[i] );
563
564            camellia_crypt_ecb( ctx, mode, output, output );
565            memcpy( iv, output, 16 );
566
567            input  += 16;
568            output += 16;
569            length -= 16;
570        }
571    }
572
573    return( 0 );
574}
575
576#if defined(POLARSSL_CIPHER_MODE_CFB)
577/*
578 * Camellia-CFB128 buffer encryption/decryption
579 */
580int camellia_crypt_cfb128( camellia_context *ctx,
581                       int mode,
582                       size_t length,
583                       size_t *iv_off,
584                       unsigned char iv[16],
585                       const unsigned char *input,
586                       unsigned char *output )
587{
588    int c;
589    size_t n = *iv_off;
590
591    if( mode == CAMELLIA_DECRYPT )
592    {
593        while( length-- )
594        {
595            if( n == 0 )
596                camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
597
598            c = *input++;
599            *output++ = (unsigned char)( c ^ iv[n] );
600            iv[n] = (unsigned char) c;
601
602            n = (n + 1) & 0x0F;
603        }
604    }
605    else
606    {
607        while( length-- )
608        {
609            if( n == 0 )
610                camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
611
612            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
613
614            n = (n + 1) & 0x0F;
615        }
616    }
617
618    *iv_off = n;
619
620    return( 0 );
621}
622#endif /* POLARSSL_CIPHER_MODE_CFB */
623
624#if defined(POLARSSL_CIPHER_MODE_CTR)
625/*
626 * Camellia-CTR buffer encryption/decryption
627 */
628int camellia_crypt_ctr( camellia_context *ctx,
629                       size_t length,
630                       size_t *nc_off,
631                       unsigned char nonce_counter[16],
632                       unsigned char stream_block[16],
633                       const unsigned char *input,
634                       unsigned char *output )
635{
636    int c, i;
637    size_t n = *nc_off;
638
639    while( length-- )
640    {
641        if( n == 0 ) {
642            camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter, stream_block );
643
644            for( i = 16; i > 0; i-- )
645                if( ++nonce_counter[i - 1] != 0 )
646                    break;
647        }
648        c = *input++;
649        *output++ = (unsigned char)( c ^ stream_block[n] );
650
651        n = (n + 1) & 0x0F;
652    }
653
654    *nc_off = n;
655
656    return( 0 );
657}
658#endif /* POLARSSL_CIPHER_MODE_CTR */
659
660#if defined(POLARSSL_SELF_TEST)
661
662#include <stdio.h>
663
664/*
665 * Camellia test vectors from:
666 *
667 * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html:
668 *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt
669 *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt
670 *                      (For each bitlength: Key 0, Nr 39)
671 */
672#define CAMELLIA_TESTS_ECB  2
673
674static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
675{
676    {
677        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
678          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
679        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
680          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
681    },
682    {
683        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
684          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
685          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
686        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
687          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
689    },
690    {
691        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
692          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
693          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
694          0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
695        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
696          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
699    },
700};
701
702static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =
703{
704    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
705      0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
706    { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
707      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
708};
709
710static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] =
711{
712    {
713        { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
714          0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
715        { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE,
716          0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 }
717    },
718    {
719        { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
720          0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
721        { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9,
722          0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 }
723    },
724    {
725        { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
726          0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
727        { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C,
728          0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 }
729    }
730};
731
732#define CAMELLIA_TESTS_CBC  3
733
734static const unsigned char camellia_test_cbc_key[3][32] =
735{
736        { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
737          0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
738    ,
739        { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
740          0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
741          0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
742    ,
743        { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
744          0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
745          0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
746          0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
747};
748
749static const unsigned char camellia_test_cbc_iv[16] =
750
751    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
752      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
753;
754
755static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =
756{
757    { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
758      0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A },
759    { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
760      0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 },
761    { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
762      0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF }
763
764};
765
766static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] =
767{
768    {
769        { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,
770          0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB },
771        { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78,
772          0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 },
773        { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B,
774          0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 }
775    },
776    {
777        { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,
778          0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 },
779        { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42,
780          0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 },
781        { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8,
782          0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 }
783    },
784    {
785        { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,
786          0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA },
787        { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40,
788          0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 },
789        { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA,
790          0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 }
791    }
792};
793
794#if defined(POLARSSL_CIPHER_MODE_CTR)
795/*
796 * Camellia-CTR test vectors from:
797 *
798 * http://www.faqs.org/rfcs/rfc5528.html
799 */
800
801static const unsigned char camellia_test_ctr_key[3][16] =
802{
803    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
804      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
805    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
806      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
807    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
808      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
809};
810
811static const unsigned char camellia_test_ctr_nonce_counter[3][16] =
812{
813    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
814      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
815    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
816      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
817    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
818      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
819};
820
821static const unsigned char camellia_test_ctr_pt[3][48] =
822{
823    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
824      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
825
826    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
827      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
828      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
829      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
830
831    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
832      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
833      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
834      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
835      0x20, 0x21, 0x22, 0x23 }
836};
837
838static const unsigned char camellia_test_ctr_ct[3][48] =
839{
840    { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A,
841      0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F },
842    { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4,
843      0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44,
844      0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7,
845      0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 },
846    { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88,
847      0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73,
848      0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1,
849      0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD,
850      0xDF, 0x50, 0x86, 0x96 }
851};
852
853static const int camellia_test_ctr_len[3] =
854    { 16, 32, 36 };
855#endif /* POLARSSL_CIPHER_MODE_CTR */
856
857/*
858 * Checkup routine
859 */
860int camellia_self_test( int verbose )
861{
862    int i, j, u, v;
863    unsigned char key[32];
864    unsigned char buf[64];
865    unsigned char src[16];
866    unsigned char dst[16];
867    unsigned char iv[16];
868#if defined(POLARSSL_CIPHER_MODE_CTR)
869    size_t offset, len;
870    unsigned char nonce_counter[16];
871    unsigned char stream_block[16];
872#endif
873
874    camellia_context ctx;
875
876    memset( key, 0, 32 );
877
878    for (j = 0; j < 6; j++) {
879        u = j >> 1;
880    v = j & 1;
881
882    if( verbose != 0 )
883        printf( "  CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
884                (v == CAMELLIA_DECRYPT) ? "dec" : "enc");
885
886    for (i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
887        memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u);
888
889        if (v == CAMELLIA_DECRYPT) {
890            camellia_setkey_dec(&ctx, key, 128 + u * 64);
891            memcpy(src, camellia_test_ecb_cipher[u][i], 16);
892            memcpy(dst, camellia_test_ecb_plain[i], 16);
893        } else { /* CAMELLIA_ENCRYPT */
894            camellia_setkey_enc(&ctx, key, 128 + u * 64);
895            memcpy(src, camellia_test_ecb_plain[i], 16);
896            memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
897        }
898
899        camellia_crypt_ecb(&ctx, v, src, buf);
900
901        if( memcmp( buf, dst, 16 ) != 0 )
902        {
903            if( verbose != 0 )
904                printf( "failed\n" );
905
906            return( 1 );
907        }
908    }
909
910    if( verbose != 0 )
911        printf( "passed\n" );
912    }
913
914    if( verbose != 0 )
915        printf( "\n" );
916
917    /*
918     * CBC mode
919     */
920    for( j = 0; j < 6; j++ )
921    {
922        u = j >> 1;
923        v = j  & 1;
924
925        if( verbose != 0 )
926            printf( "  CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
927                    ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
928
929    memcpy( src, camellia_test_cbc_iv, 16);
930    memcpy( dst, camellia_test_cbc_iv, 16);
931    memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u);
932
933    if (v == CAMELLIA_DECRYPT) {
934        camellia_setkey_dec(&ctx, key, 128 + u * 64);
935    } else {
936        camellia_setkey_enc(&ctx, key, 128 + u * 64);
937    }
938
939    for (i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
940
941        if (v == CAMELLIA_DECRYPT) {
942            memcpy( iv , src, 16 );
943            memcpy(src, camellia_test_cbc_cipher[u][i], 16);
944            memcpy(dst, camellia_test_cbc_plain[i], 16);
945        } else { /* CAMELLIA_ENCRYPT */
946            memcpy( iv , dst, 16 );
947            memcpy(src, camellia_test_cbc_plain[i], 16);
948            memcpy(dst, camellia_test_cbc_cipher[u][i], 16);
949        }
950
951        camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);
952
953        if( memcmp( buf, dst, 16 ) != 0 )
954        {
955            if( verbose != 0 )
956                printf( "failed\n" );
957
958            return( 1 );
959        }
960    }
961
962        if( verbose != 0 )
963            printf( "passed\n" );
964    }
965
966    if( verbose != 0 )
967        printf( "\n" );
968
969#if defined(POLARSSL_CIPHER_MODE_CTR)
970    /*
971     * CTR mode
972     */
973    for( i = 0; i < 6; i++ )
974    {
975        u = i >> 1;
976        v = i  & 1;
977
978        if( verbose != 0 )
979            printf( "  CAMELLIA-CTR-128 (%s): ",
980                    ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
981
982        memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
983        memcpy( key, camellia_test_ctr_key[u], 16 );
984
985        offset = 0;
986        camellia_setkey_enc( &ctx, key, 128 );
987
988        if( v == CAMELLIA_DECRYPT )
989        {
990            len = camellia_test_ctr_len[u];
991            memcpy( buf, camellia_test_ctr_ct[u], len );
992
993            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
994
995            if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
996            {
997                if( verbose != 0 )
998                    printf( "failed\n" );
999
1000                return( 1 );
1001            }
1002        }
1003        else
1004        {
1005            len = camellia_test_ctr_len[u];
1006            memcpy( buf, camellia_test_ctr_pt[u], len );
1007
1008            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
1009
1010            if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
1011            {
1012                if( verbose != 0 )
1013                    printf( "failed\n" );
1014
1015                return( 1 );
1016            }
1017        }
1018
1019        if( verbose != 0 )
1020            printf( "passed\n" );
1021    }
1022
1023    if( verbose != 0 )
1024        printf( "\n" );
1025#endif /* POLARSSL_CIPHER_MODE_CTR */
1026
1027    return ( 0 );
1028}
1029
1030#endif
1031
1032#endif
Note: See TracBrowser for help on using the repository browser.

What are you looking for?