Convert bulk CTR and CBC selftest functions in Camellia to generic selftest helper...
[libgcrypt.git] / cipher / camellia-glue.c
1 /* camellia-glue.c - Glue for the Camellia cipher
2  * Copyright (C) 2007 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21
22 /* I put all the libgcrypt-specific stuff in this file to keep the
23    camellia.c/camellia.h files exactly as provided by NTT.  If they
24    update their code, this should make it easier to bring the changes
25    in. - dshaw
26
27    There is one small change which needs to be done: Include the
28    following code at the top of camellia.h: */
29 #if 0
30
31 /* To use Camellia with libraries it is often useful to keep the name
32  * space of the library clean.  The following macro is thus useful:
33  *
34  *     #define CAMELLIA_EXT_SYM_PREFIX foo_
35  *
36  * This prefixes all external symbols with "foo_".
37  */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41 #ifdef CAMELLIA_EXT_SYM_PREFIX
42 #define CAMELLIA_PREFIX1(x,y) x ## y
43 #define CAMELLIA_PREFIX2(x,y) CAMELLIA_PREFIX1(x,y)
44 #define CAMELLIA_PREFIX(x)    CAMELLIA_PREFIX2(CAMELLIA_EXT_SYM_PREFIX,x)
45 #define Camellia_Ekeygen      CAMELLIA_PREFIX(Camellia_Ekeygen)
46 #define Camellia_EncryptBlock CAMELLIA_PREFIX(Camellia_EncryptBlock)
47 #define Camellia_DecryptBlock CAMELLIA_PREFIX(Camellia_DecryptBlock)
48 #define camellia_decrypt128   CAMELLIA_PREFIX(camellia_decrypt128)
49 #define camellia_decrypt256   CAMELLIA_PREFIX(camellia_decrypt256)
50 #define camellia_encrypt128   CAMELLIA_PREFIX(camellia_encrypt128)
51 #define camellia_encrypt256   CAMELLIA_PREFIX(camellia_encrypt256)
52 #define camellia_setup128     CAMELLIA_PREFIX(camellia_setup128)
53 #define camellia_setup192     CAMELLIA_PREFIX(camellia_setup192)
54 #define camellia_setup256     CAMELLIA_PREFIX(camellia_setup256)
55 #endif /*CAMELLIA_EXT_SYM_PREFIX*/
56
57 #endif /* Code sample. */
58
59
60 #include <config.h>
61 #include "types.h"
62 #include "g10lib.h"
63 #include "cipher.h"
64 #include "camellia.h"
65 #include "bufhelp.h"
66 #include "cipher-selftest.h"
67
68 /* Helper macro to force alignment to 16 bytes.  */
69 #ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
70 # define ATTR_ALIGNED_16  __attribute__ ((aligned (16)))
71 #else
72 # define ATTR_ALIGNED_16
73 #endif
74
75 /* USE_AESNI inidicates whether to compile with Intel AES-NI/AVX code. */
76 #undef USE_AESNI_AVX
77 #if defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)
78 # if defined(__x86_64__)
79 #  define USE_AESNI_AVX 1
80 # endif
81 #endif
82
83 typedef struct
84 {
85   int keybitlength;
86   KEY_TABLE_TYPE keytable;
87 #ifdef USE_AESNI_AVX
88   int use_aesni_avx;            /* AES-NI/AVX implementation shall be used.  */
89 #endif /*USE_AESNI_AVX*/
90 } CAMELLIA_context;
91
92 #ifdef USE_AESNI_AVX
93 /* Assembler implementations of Camellia using AES-NI and AVX.  Process data
94    in 16 block same time.
95  */
96 extern void _gcry_camellia_aesni_avx_ctr_enc(CAMELLIA_context *ctx,
97                                              unsigned char *out,
98                                              const unsigned char *in,
99                                              unsigned char *ctr);
100
101 extern void _gcry_camellia_aesni_avx_cbc_dec(CAMELLIA_context *ctx,
102                                              unsigned char *out,
103                                              const unsigned char *in,
104                                              unsigned char *iv);
105 #endif
106
107 static const char *selftest(void);
108
109 static gcry_err_code_t
110 camellia_setkey(void *c, const byte *key, unsigned keylen)
111 {
112   CAMELLIA_context *ctx=c;
113   static int initialized=0;
114   static const char *selftest_failed=NULL;
115
116   if(keylen!=16 && keylen!=24 && keylen!=32)
117     return GPG_ERR_INV_KEYLEN;
118
119   if(!initialized)
120     {
121       initialized=1;
122       selftest_failed=selftest();
123       if(selftest_failed)
124         log_error("%s\n",selftest_failed);
125     }
126
127   if(selftest_failed)
128     return GPG_ERR_SELFTEST_FAILED;
129
130   ctx->keybitlength=keylen*8;
131   Camellia_Ekeygen(ctx->keybitlength,key,ctx->keytable);
132   _gcry_burn_stack
133     ((19+34+34)*sizeof(u32)+2*sizeof(void*) /* camellia_setup256 */
134      +(4+32)*sizeof(u32)+2*sizeof(void*)    /* camellia_setup192 */
135      +0+sizeof(int)+2*sizeof(void*)         /* Camellia_Ekeygen */
136      +3*2*sizeof(void*)                     /* Function calls.  */
137      );
138
139 #ifdef USE_AESNI_AVX
140   ctx->use_aesni_avx = 0;
141   if ((_gcry_get_hw_features () & HWF_INTEL_AESNI) &&
142       (_gcry_get_hw_features () & HWF_INTEL_AVX))
143     {
144       ctx->use_aesni_avx = 1;
145     }
146 #endif
147
148   return 0;
149 }
150
151 static void
152 camellia_encrypt(void *c, byte *outbuf, const byte *inbuf)
153 {
154   CAMELLIA_context *ctx=c;
155
156   Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
157
158 #define CAMELLIA_encrypt_stack_burn_size \
159   (sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/) \
160      +4*sizeof(u32)+4*sizeof(u32) \
161      +2*sizeof(u32*)+4*sizeof(u32) \
162      +2*2*sizeof(void*) /* Function calls.  */ \
163     )
164
165   _gcry_burn_stack(CAMELLIA_encrypt_stack_burn_size);
166 }
167
168 static void
169 camellia_decrypt(void *c, byte *outbuf, const byte *inbuf)
170 {
171   CAMELLIA_context *ctx=c;
172
173   Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
174
175 #define CAMELLIA_decrypt_stack_burn_size \
176     (sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/) \
177      +4*sizeof(u32)+4*sizeof(u32) \
178      +2*sizeof(u32*)+4*sizeof(u32) \
179      +2*2*sizeof(void*) /* Function calls.  */ \
180     )
181
182   _gcry_burn_stack(CAMELLIA_decrypt_stack_burn_size);
183 }
184
185 /* Bulk encryption of complete blocks in CTR mode.  This function is only
186    intended for the bulk encryption feature of cipher.c.  CTR is expected to be
187    of size CAMELLIA_BLOCK_SIZE. */
188 void
189 _gcry_camellia_ctr_enc(void *context, unsigned char *ctr,
190                        void *outbuf_arg, const void *inbuf_arg,
191                        unsigned int nblocks)
192 {
193   CAMELLIA_context *ctx = context;
194   unsigned char *outbuf = outbuf_arg;
195   const unsigned char *inbuf = inbuf_arg;
196   unsigned char tmpbuf[CAMELLIA_BLOCK_SIZE];
197   int burn_stack_depth = CAMELLIA_encrypt_stack_burn_size;
198   int i;
199
200 #ifdef USE_AESNI_AVX
201   if (ctx->use_aesni_avx)
202     {
203       int did_use_aesni_avx = 0;
204
205       /* Process data in 16 block chunks. */
206       while (nblocks >= 16)
207         {
208           _gcry_camellia_aesni_avx_ctr_enc(ctx, outbuf, inbuf, ctr);
209
210           nblocks -= 16;
211           outbuf += 16 * CAMELLIA_BLOCK_SIZE;
212           inbuf  += 16 * CAMELLIA_BLOCK_SIZE;
213           did_use_aesni_avx = 1;
214         }
215
216       if (did_use_aesni_avx)
217         {
218           /* clear AVX registers */
219           asm volatile ("vzeroall;\n":::);
220
221           if (burn_stack_depth < 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *))
222             burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *);
223         }
224
225       /* Use generic code to handle smaller chunks... */
226       /* TODO: use caching instead? */
227     }
228 #endif
229
230   for ( ;nblocks; nblocks-- )
231     {
232       /* Encrypt the counter. */
233       Camellia_EncryptBlock(ctx->keybitlength, ctr, ctx->keytable, tmpbuf);
234       /* XOR the input with the encrypted counter and store in output.  */
235       buf_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE);
236       outbuf += CAMELLIA_BLOCK_SIZE;
237       inbuf  += CAMELLIA_BLOCK_SIZE;
238       /* Increment the counter.  */
239       for (i = CAMELLIA_BLOCK_SIZE; i > 0; i--)
240         {
241           ctr[i-1]++;
242           if (ctr[i-1])
243             break;
244         }
245     }
246
247   wipememory(tmpbuf, sizeof(tmpbuf));
248   _gcry_burn_stack(burn_stack_depth);
249 }
250
251 /* Bulk decryption of complete blocks in CBC mode.  This function is only
252    intended for the bulk encryption feature of cipher.c. */
253 void
254 _gcry_camellia_cbc_dec(void *context, unsigned char *iv,
255                        void *outbuf_arg, const void *inbuf_arg,
256                        unsigned int nblocks)
257 {
258   CAMELLIA_context *ctx = context;
259   unsigned char *outbuf = outbuf_arg;
260   const unsigned char *inbuf = inbuf_arg;
261   unsigned char savebuf[CAMELLIA_BLOCK_SIZE];
262   int burn_stack_depth = CAMELLIA_decrypt_stack_burn_size;
263
264 #ifdef USE_AESNI_AVX
265   if (ctx->use_aesni_avx)
266     {
267       int did_use_aesni_avx = 0;
268
269       /* Process data in 16 block chunks. */
270       while (nblocks >= 16)
271         {
272           _gcry_camellia_aesni_avx_cbc_dec(ctx, outbuf, inbuf, iv);
273
274           nblocks -= 16;
275           outbuf += 16 * CAMELLIA_BLOCK_SIZE;
276           inbuf  += 16 * CAMELLIA_BLOCK_SIZE;
277           did_use_aesni_avx = 1;
278         }
279
280       if (did_use_aesni_avx)
281         {
282           /* clear AVX registers */
283           asm volatile ("vzeroall;\n":::);
284
285           if (burn_stack_depth < 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *))
286             burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *);
287         }
288
289       /* Use generic code to handle smaller chunks... */
290     }
291 #endif
292
293   for ( ;nblocks; nblocks-- )
294     {
295       /* We need to save INBUF away because it may be identical to
296          OUTBUF.  */
297       memcpy(savebuf, inbuf, CAMELLIA_BLOCK_SIZE);
298
299       Camellia_DecryptBlock(ctx->keybitlength, inbuf, ctx->keytable, outbuf);
300
301       buf_xor(outbuf, outbuf, iv, CAMELLIA_BLOCK_SIZE);
302       memcpy(iv, savebuf, CAMELLIA_BLOCK_SIZE);
303       inbuf += CAMELLIA_BLOCK_SIZE;
304       outbuf += CAMELLIA_BLOCK_SIZE;
305     }
306
307   wipememory(savebuf, sizeof(savebuf));
308   _gcry_burn_stack(burn_stack_depth);
309 }
310
311 /* Run the self-tests for CAMELLIA-CTR-128, tests IV increment of bulk CTR
312    encryption.  Returns NULL on success. */
313 static const char*
314 selftest_ctr_128 (void)
315 {
316   const int nblocks = 16+1;
317   const int blocksize = CAMELLIA_BLOCK_SIZE;
318   const int context_size = sizeof(CAMELLIA_context);
319
320   return _gcry_selftest_helper_ctr_128("CAMELLIA", &camellia_setkey,
321            &camellia_encrypt, &_gcry_camellia_ctr_enc, nblocks, blocksize,
322            context_size);
323 }
324
325 /* Run the self-tests for CAMELLIA-CBC-128, tests bulk CBC decryption.
326    Returns NULL on success. */
327 static const char*
328 selftest_cbc_128 (void)
329 {
330   const int nblocks = 16+2;
331   const int blocksize = CAMELLIA_BLOCK_SIZE;
332   const int context_size = sizeof(CAMELLIA_context);
333
334   return _gcry_selftest_helper_cbc_128("CAMELLIA", &camellia_setkey,
335            &camellia_encrypt, &_gcry_camellia_cbc_dec, nblocks, blocksize,
336            context_size);
337 }
338
339 static const char *
340 selftest(void)
341 {
342   CAMELLIA_context ctx;
343   byte scratch[16];
344   const char *r;
345
346   /* These test vectors are from RFC-3713 */
347   const byte plaintext[]=
348     {
349       0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
350       0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10
351     };
352   const byte key_128[]=
353     {
354       0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
355       0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10
356     };
357   const byte ciphertext_128[]=
358     {
359       0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73,
360       0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43
361     };
362   const byte key_192[]=
363     {
364       0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,
365       0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77
366     };
367   const byte ciphertext_192[]=
368     {
369       0xb4,0x99,0x34,0x01,0xb3,0xe9,0x96,0xf8,
370       0x4e,0xe5,0xce,0xe7,0xd7,0x9b,0x09,0xb9
371     };
372   const byte key_256[]=
373     {
374       0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,
375       0x98,0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,
376       0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff
377     };
378   const byte ciphertext_256[]=
379     {
380       0x9a,0xcc,0x23,0x7d,0xff,0x16,0xd7,0x6c,
381       0x20,0xef,0x7c,0x91,0x9e,0x3a,0x75,0x09
382     };
383
384   camellia_setkey(&ctx,key_128,sizeof(key_128));
385   camellia_encrypt(&ctx,scratch,plaintext);
386   if(memcmp(scratch,ciphertext_128,sizeof(ciphertext_128))!=0)
387     return "CAMELLIA-128 test encryption failed.";
388   camellia_decrypt(&ctx,scratch,scratch);
389   if(memcmp(scratch,plaintext,sizeof(plaintext))!=0)
390     return "CAMELLIA-128 test decryption failed.";
391
392   camellia_setkey(&ctx,key_192,sizeof(key_192));
393   camellia_encrypt(&ctx,scratch,plaintext);
394   if(memcmp(scratch,ciphertext_192,sizeof(ciphertext_192))!=0)
395     return "CAMELLIA-192 test encryption failed.";
396   camellia_decrypt(&ctx,scratch,scratch);
397   if(memcmp(scratch,plaintext,sizeof(plaintext))!=0)
398     return "CAMELLIA-192 test decryption failed.";
399
400   camellia_setkey(&ctx,key_256,sizeof(key_256));
401   camellia_encrypt(&ctx,scratch,plaintext);
402   if(memcmp(scratch,ciphertext_256,sizeof(ciphertext_256))!=0)
403     return "CAMELLIA-256 test encryption failed.";
404   camellia_decrypt(&ctx,scratch,scratch);
405   if(memcmp(scratch,plaintext,sizeof(plaintext))!=0)
406     return "CAMELLIA-256 test decryption failed.";
407
408   if ( (r = selftest_ctr_128 ()) )
409     return r;
410
411   if ( (r = selftest_cbc_128 ()) )
412     return r;
413
414   return NULL;
415 }
416
417 /* These oids are from
418    <http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications_oid.html>,
419    retrieved May 1, 2007. */
420
421 static gcry_cipher_oid_spec_t camellia128_oids[] =
422   {
423     {"1.2.392.200011.61.1.1.1.2", GCRY_CIPHER_MODE_CBC},
424     {"0.3.4401.5.3.1.9.1", GCRY_CIPHER_MODE_ECB},
425     {"0.3.4401.5.3.1.9.3", GCRY_CIPHER_MODE_OFB},
426     {"0.3.4401.5.3.1.9.4", GCRY_CIPHER_MODE_CFB},
427     { NULL }
428   };
429
430 static gcry_cipher_oid_spec_t camellia192_oids[] =
431   {
432     {"1.2.392.200011.61.1.1.1.3", GCRY_CIPHER_MODE_CBC},
433     {"0.3.4401.5.3.1.9.21", GCRY_CIPHER_MODE_ECB},
434     {"0.3.4401.5.3.1.9.23", GCRY_CIPHER_MODE_OFB},
435     {"0.3.4401.5.3.1.9.24", GCRY_CIPHER_MODE_CFB},
436     { NULL }
437   };
438
439 static gcry_cipher_oid_spec_t camellia256_oids[] =
440   {
441     {"1.2.392.200011.61.1.1.1.4", GCRY_CIPHER_MODE_CBC},
442     {"0.3.4401.5.3.1.9.41", GCRY_CIPHER_MODE_ECB},
443     {"0.3.4401.5.3.1.9.43", GCRY_CIPHER_MODE_OFB},
444     {"0.3.4401.5.3.1.9.44", GCRY_CIPHER_MODE_CFB},
445     { NULL }
446   };
447
448 gcry_cipher_spec_t _gcry_cipher_spec_camellia128 =
449   {
450     "CAMELLIA128",NULL,camellia128_oids,CAMELLIA_BLOCK_SIZE,128,
451     sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt
452   };
453
454 gcry_cipher_spec_t _gcry_cipher_spec_camellia192 =
455   {
456     "CAMELLIA192",NULL,camellia192_oids,CAMELLIA_BLOCK_SIZE,192,
457     sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt
458   };
459
460 gcry_cipher_spec_t _gcry_cipher_spec_camellia256 =
461   {
462     "CAMELLIA256",NULL,camellia256_oids,CAMELLIA_BLOCK_SIZE,256,
463     sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt
464   };