source: trunk/library/camellia.c @ 1121

Revision 1121, 32.7 KB checked in by paul, 3 months ago (diff)
  • Cleaned up define
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, cb;
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            i = 15;
645            do {
646               nonce_counter[i]++;
647               cb = nonce_counter[i] == 0;
648            } while( i-- && cb );
649
650        }
651        c = *input++;
652        *output++ = (unsigned char)( c ^ stream_block[n] );
653
654        n = (n + 1) & 0x0F;
655    }
656
657    *nc_off = n;
658
659    return( 0 );
660}
661#endif /* POLARSSL_CIPHER_MODE_CTR */
662
663#if defined(POLARSSL_SELF_TEST)
664
665#include <stdio.h>
666
667/*
668 * Camellia test vectors from:
669 *
670 * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html:
671 *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt
672 *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt
673 *                      (For each bitlength: Key 0, Nr 39)
674 */
675#define CAMELLIA_TESTS_ECB  2
676
677static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
678{
679    {
680        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
681          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
682        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
683          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
684    },
685    {
686        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
687          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
688          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
689        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
690          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
692    },
693    {
694        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
695          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
696          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
697          0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
698        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
699          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
702    },
703};
704
705static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =
706{
707    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
708      0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
709    { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
710      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
711};
712
713static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] =
714{
715    {
716        { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
717          0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
718        { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE,
719          0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 }
720    },
721    {
722        { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
723          0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
724        { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9,
725          0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 }
726    },
727    {
728        { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
729          0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
730        { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C,
731          0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 }
732    }
733};
734
735#define CAMELLIA_TESTS_CBC  3
736
737static const unsigned char camellia_test_cbc_key[3][32] =
738{
739        { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
740          0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
741    ,
742        { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
743          0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
744          0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
745    ,
746        { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
747          0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
748          0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
749          0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
750};
751
752static const unsigned char camellia_test_cbc_iv[16] =
753
754    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
755      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
756;
757
758static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =
759{
760    { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
761      0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A },
762    { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
763      0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 },
764    { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
765      0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF }
766
767};
768
769static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] =
770{
771    {
772        { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,
773          0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB },
774        { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78,
775          0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 },
776        { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B,
777          0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 }
778    },
779    {
780        { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,
781          0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 },
782        { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42,
783          0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 },
784        { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8,
785          0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 }
786    },
787    {
788        { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,
789          0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA },
790        { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40,
791          0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 },
792        { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA,
793          0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 }
794    }
795};
796
797#if defined(POLARSSL_CIPHER_MODE_CTR)
798/*
799 * Camellia-CTR test vectors from:
800 *
801 * http://www.faqs.org/rfcs/rfc5528.html
802 */
803
804static const unsigned char camellia_test_ctr_key[3][16] =
805{
806    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
807      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
808    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
809      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
810    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
811      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
812};
813
814static const unsigned char camellia_test_ctr_nonce_counter[3][16] =
815{
816    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
817      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
818    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
819      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
820    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
821      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
822};
823
824static const unsigned char camellia_test_ctr_pt[3][48] =
825{
826    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
827      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
828
829    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
830      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
831      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
832      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
833
834    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
835      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
836      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
837      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
838      0x20, 0x21, 0x22, 0x23 }
839};
840
841static const unsigned char camellia_test_ctr_ct[3][48] =
842{
843    { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A,
844      0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F },
845    { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4,
846      0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44,
847      0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7,
848      0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 },
849    { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88,
850      0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73,
851      0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1,
852      0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD,
853      0xDF, 0x50, 0x86, 0x96 }
854};
855
856static const int camellia_test_ctr_len[3] =
857    { 16, 32, 36 };
858#endif /* POLARSSL_CIPHER_MODE_CTR */
859
860/*
861 * Checkup routine
862 */
863int camellia_self_test( int verbose )
864{
865    int i, j, u, v;
866    unsigned char key[32];
867    unsigned char buf[64];
868    unsigned char src[16];
869    unsigned char dst[16];
870    unsigned char iv[16];
871#if defined(POLARSSL_CIPHER_MODE_CTR)
872    size_t offset, len;
873    unsigned char nonce_counter[16];
874    unsigned char stream_block[16];
875#endif
876
877    camellia_context ctx;
878
879    memset( key, 0, 32 );
880
881    for (j = 0; j < 6; j++) {
882        u = j >> 1;
883    v = j & 1;
884
885    if( verbose != 0 )
886        printf( "  CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
887                (v == CAMELLIA_DECRYPT) ? "dec" : "enc");
888
889    for (i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
890        memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u);
891
892        if (v == CAMELLIA_DECRYPT) {
893            camellia_setkey_dec(&ctx, key, 128 + u * 64);
894            memcpy(src, camellia_test_ecb_cipher[u][i], 16);
895            memcpy(dst, camellia_test_ecb_plain[i], 16);
896        } else { /* CAMELLIA_ENCRYPT */
897            camellia_setkey_enc(&ctx, key, 128 + u * 64);
898            memcpy(src, camellia_test_ecb_plain[i], 16);
899            memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
900        }
901
902        camellia_crypt_ecb(&ctx, v, src, buf);
903
904        if( memcmp( buf, dst, 16 ) != 0 )
905        {
906            if( verbose != 0 )
907                printf( "failed\n" );
908
909            return( 1 );
910        }
911    }
912
913    if( verbose != 0 )
914        printf( "passed\n" );
915    }
916
917    if( verbose != 0 )
918        printf( "\n" );
919
920    /*
921     * CBC mode
922     */
923    for( j = 0; j < 6; j++ )
924    {
925        u = j >> 1;
926        v = j  & 1;
927
928        if( verbose != 0 )
929            printf( "  CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
930                    ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
931
932    memcpy( src, camellia_test_cbc_iv, 16);
933    memcpy( dst, camellia_test_cbc_iv, 16);
934    memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u);
935
936    if (v == CAMELLIA_DECRYPT) {
937        camellia_setkey_dec(&ctx, key, 128 + u * 64);
938    } else {
939        camellia_setkey_enc(&ctx, key, 128 + u * 64);
940    }
941
942    for (i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
943
944        if (v == CAMELLIA_DECRYPT) {
945            memcpy( iv , src, 16 );
946            memcpy(src, camellia_test_cbc_cipher[u][i], 16);
947            memcpy(dst, camellia_test_cbc_plain[i], 16);
948        } else { /* CAMELLIA_ENCRYPT */
949            memcpy( iv , dst, 16 );
950            memcpy(src, camellia_test_cbc_plain[i], 16);
951            memcpy(dst, camellia_test_cbc_cipher[u][i], 16);
952        }
953
954        camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);
955
956        if( memcmp( buf, dst, 16 ) != 0 )
957        {
958            if( verbose != 0 )
959                printf( "failed\n" );
960
961            return( 1 );
962        }
963    }
964
965        if( verbose != 0 )
966            printf( "passed\n" );
967    }
968
969    if( verbose != 0 )
970        printf( "\n" );
971
972#if defined(POLARSSL_CIPHER_MODE_CTR)
973    /*
974     * CTR mode
975     */
976    for( i = 0; i < 6; i++ )
977    {
978        u = i >> 1;
979        v = i  & 1;
980
981        if( verbose != 0 )
982            printf( "  CAMELLIA-CTR-128 (%s): ",
983                    ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
984
985        memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
986        memcpy( key, camellia_test_ctr_key[u], 16 );
987
988        offset = 0;
989        camellia_setkey_enc( &ctx, key, 128 );
990
991        if( v == CAMELLIA_DECRYPT )
992        {
993            len = camellia_test_ctr_len[u];
994            memcpy( buf, camellia_test_ctr_ct[u], len );
995
996            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
997
998            if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
999            {
1000                if( verbose != 0 )
1001                    printf( "failed\n" );
1002
1003                return( 1 );
1004            }
1005        }
1006        else
1007        {
1008            len = camellia_test_ctr_len[u];
1009            memcpy( buf, camellia_test_ctr_pt[u], len );
1010
1011            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
1012
1013            if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
1014            {
1015                if( verbose != 0 )
1016                    printf( "failed\n" );
1017
1018                return( 1 );
1019            }
1020        }
1021
1022        if( verbose != 0 )
1023            printf( "passed\n" );
1024    }
1025
1026    if( verbose != 0 )
1027        printf( "\n" );
1028#endif /* POLARSSL_CIPHER_MODE_CTR */
1029
1030    return ( 0 );
1031}
1032
1033#endif
1034
1035#endif
Note: See TracBrowser for help on using the repository browser.

What are you looking for?