Remove macro hacks for internal vs. external functions. Part 2 and last.
[libgcrypt.git] / cipher / cipher-selftest.c
1 /* cipher-selftest.c - Helper functions for bulk encryption selftests.
2  *      Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
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 Lesser 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #ifdef HAVE_SYSLOG
22 # include <syslog.h>
23 #endif /*HAVE_SYSLOG*/
24
25 #include "types.h"
26 #include "g10lib.h"
27 #include "cipher.h"
28 #include "bufhelp.h"
29 #include "cipher-selftest.h"
30
31 #ifdef HAVE_STDINT_H
32 # include <stdint.h> /* uintptr_t */
33 #elif defined(HAVE_INTTYPES_H)
34 # include <inttypes.h>
35 #else
36 /* In this case, uintptr_t is provided by config.h. */
37 #endif
38
39 /* Helper macro to force alignment to 16 bytes.  */
40 #ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
41 # define ATTR_ALIGNED_16  __attribute__ ((aligned (16)))
42 #else
43 # define ATTR_ALIGNED_16
44 #endif
45
46
47 /* Run the self-tests for <block cipher>-CBC-<block size>, tests bulk CBC
48    decryption.  Returns NULL on success. */
49 const char *
50 _gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey_func,
51                            gcry_cipher_encrypt_t encrypt_one,
52                            gcry_cipher_bulk_cbc_dec_t bulk_cbc_dec,
53                            const int nblocks, const int blocksize,
54                            const int context_size)
55 {
56   int i, offs;
57   unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem;
58   unsigned int ctx_aligned_size, memsize;
59
60   static const unsigned char key[16] ATTR_ALIGNED_16 = {
61       0x66,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
62       0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x22
63     };
64
65   /* Allocate buffers, align first two elements to 16 bytes and latter to
66      block size.  */
67   ctx_aligned_size = context_size + 15;
68   ctx_aligned_size -= ctx_aligned_size & 0xf;
69
70   memsize = ctx_aligned_size + (blocksize * 2) + (blocksize * nblocks * 3) + 16;
71
72   mem = xtrycalloc (1, memsize);
73   if (!mem)
74     return "failed to allocate memory";
75
76   offs = (16 - ((uintptr_t)mem & 15)) & 15;
77   ctx = (void*)(mem + offs);
78   iv = ctx + ctx_aligned_size;
79   iv2 = iv + blocksize;
80   plaintext = iv2 + blocksize;
81   plaintext2 = plaintext + nblocks * blocksize;
82   ciphertext = plaintext2 + nblocks * blocksize;
83
84   /* Initialize ctx */
85   setkey_func (ctx, key, sizeof(key));
86
87   /* Test single block code path */
88   memset (iv, 0x4e, blocksize);
89   memset (iv2, 0x4e, blocksize);
90   for (i = 0; i < blocksize; i++)
91     plaintext[i] = i;
92
93   /* CBC manually.  */
94   buf_xor (ciphertext, iv, plaintext, blocksize);
95   encrypt_one (ctx, ciphertext, ciphertext);
96   memcpy (iv, ciphertext, blocksize);
97
98   /* CBC decrypt.  */
99   bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, 1);
100   if (memcmp (plaintext2, plaintext, blocksize))
101     {
102       xfree (mem);
103 #ifdef HAVE_SYSLOG
104       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
105               "%s-CBC-%d test failed (plaintext mismatch)", cipher,
106               blocksize * 8);
107 #endif
108       return "selftest for CBC failed - see syslog for details";
109     }
110
111   if (memcmp (iv2, iv, blocksize))
112     {
113       xfree (mem);
114 #ifdef HAVE_SYSLOG
115       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
116               "%s-CBC-%d test failed (IV mismatch)", cipher, blocksize * 8);
117 #endif
118       return "selftest for CBC failed - see syslog for details";
119     }
120
121   /* Test parallelized code paths */
122   memset (iv, 0x5f, blocksize);
123   memset (iv2, 0x5f, blocksize);
124
125   for (i = 0; i < nblocks * blocksize; i++)
126     plaintext[i] = i;
127
128   /* Create CBC ciphertext manually.  */
129   for (i = 0; i < nblocks * blocksize; i+=blocksize)
130     {
131       buf_xor (&ciphertext[i], iv, &plaintext[i], blocksize);
132       encrypt_one (ctx, &ciphertext[i], &ciphertext[i]);
133       memcpy (iv, &ciphertext[i], blocksize);
134     }
135
136   /* Decrypt using bulk CBC and compare result.  */
137   bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, nblocks);
138
139   if (memcmp (plaintext2, plaintext, nblocks * blocksize))
140     {
141       xfree (mem);
142 #ifdef HAVE_SYSLOG
143       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
144               "%s-CBC-%d test failed (plaintext mismatch, parallel path)",
145               cipher, blocksize * 8);
146 #endif
147       return "selftest for CBC failed - see syslog for details";
148     }
149   if (memcmp (iv2, iv, blocksize))
150     {
151       xfree (mem);
152 #ifdef HAVE_SYSLOG
153       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
154               "%s-CBC-%d test failed (IV mismatch, parallel path)",
155               cipher, blocksize * 8);
156 #endif
157       return "selftest for CBC failed - see syslog for details";
158     }
159
160   xfree (mem);
161   return NULL;
162 }
163
164 /* Run the self-tests for <block cipher>-CFB-<block size>, tests bulk CFB
165    decryption.  Returns NULL on success. */
166 const char *
167 _gcry_selftest_helper_cfb (const char *cipher, gcry_cipher_setkey_t setkey_func,
168                            gcry_cipher_encrypt_t encrypt_one,
169                            gcry_cipher_bulk_cfb_dec_t bulk_cfb_dec,
170                            const int nblocks, const int blocksize,
171                            const int context_size)
172 {
173   int i, offs;
174   unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem;
175   unsigned int ctx_aligned_size, memsize;
176
177   static const unsigned char key[16] ATTR_ALIGNED_16 = {
178       0x11,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
179       0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x33
180     };
181
182   /* Allocate buffers, align first two elements to 16 bytes and latter to
183      block size.  */
184   ctx_aligned_size = context_size + 15;
185   ctx_aligned_size -= ctx_aligned_size & 0xf;
186
187   memsize = ctx_aligned_size + (blocksize * 2) + (blocksize * nblocks * 3) + 16;
188
189   mem = xtrycalloc (1, memsize);
190   if (!mem)
191     return "failed to allocate memory";
192
193   offs = (16 - ((uintptr_t)mem & 15)) & 15;
194   ctx = (void*)(mem + offs);
195   iv = ctx + ctx_aligned_size;
196   iv2 = iv + blocksize;
197   plaintext = iv2 + blocksize;
198   plaintext2 = plaintext + nblocks * blocksize;
199   ciphertext = plaintext2 + nblocks * blocksize;
200
201   /* Initialize ctx */
202   setkey_func (ctx, key, sizeof(key));
203
204   /* Test single block code path */
205   memset(iv, 0xd3, blocksize);
206   memset(iv2, 0xd3, blocksize);
207   for (i = 0; i < blocksize; i++)
208     plaintext[i] = i;
209
210   /* CFB manually.  */
211   encrypt_one (ctx, ciphertext, iv);
212   buf_xor_2dst (iv, ciphertext, plaintext, blocksize);
213
214   /* CFB decrypt.  */
215   bulk_cfb_dec (ctx, iv2, plaintext2, ciphertext, 1);
216   if (memcmp(plaintext2, plaintext, blocksize))
217     {
218       xfree(mem);
219 #ifdef HAVE_SYSLOG
220       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
221               "%s-CFB-%d test failed (plaintext mismatch)", cipher,
222               blocksize * 8);
223 #endif
224       return "selftest for CFB failed - see syslog for details";
225     }
226
227   if (memcmp(iv2, iv, blocksize))
228     {
229       xfree(mem);
230 #ifdef HAVE_SYSLOG
231       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
232               "%s-CFB-%d test failed (IV mismatch)", cipher, blocksize * 8);
233 #endif
234       return "selftest for CFB failed - see syslog for details";
235     }
236
237   /* Test parallelized code paths */
238   memset(iv, 0xe6, blocksize);
239   memset(iv2, 0xe6, blocksize);
240
241   for (i = 0; i < nblocks * blocksize; i++)
242     plaintext[i] = i;
243
244   /* Create CFB ciphertext manually.  */
245   for (i = 0; i < nblocks * blocksize; i+=blocksize)
246     {
247       encrypt_one (ctx, &ciphertext[i], iv);
248       buf_xor_2dst (iv, &ciphertext[i], &plaintext[i], blocksize);
249     }
250
251   /* Decrypt using bulk CBC and compare result.  */
252   bulk_cfb_dec (ctx, iv2, plaintext2, ciphertext, nblocks);
253
254   if (memcmp(plaintext2, plaintext, nblocks * blocksize))
255     {
256       xfree(mem);
257 #ifdef HAVE_SYSLOG
258       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
259               "%s-CFB-%d test failed (plaintext mismatch, parallel path)",
260               cipher, blocksize * 8);
261 #endif
262       return "selftest for CFB failed - see syslog for details";
263     }
264   if (memcmp(iv2, iv, blocksize))
265     {
266       xfree(mem);
267 #ifdef HAVE_SYSLOG
268       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
269               "%s-CFB-%d test failed (IV mismatch, parallel path)", cipher,
270               blocksize * 8);
271 #endif
272       return "selftest for CFB failed - see syslog for details";
273     }
274
275   xfree(mem);
276   return NULL;
277 }
278
279 /* Run the self-tests for <block cipher>-CTR-<block size>, tests IV increment
280    of bulk CTR encryption.  Returns NULL on success. */
281 const char *
282 _gcry_selftest_helper_ctr (const char *cipher, gcry_cipher_setkey_t setkey_func,
283                            gcry_cipher_encrypt_t encrypt_one,
284                            gcry_cipher_bulk_ctr_enc_t bulk_ctr_enc,
285                            const int nblocks, const int blocksize,
286                            const int context_size)
287 {
288   int i, j, offs, diff;
289   unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *ciphertext2,
290                 *iv, *iv2, *mem;
291   unsigned int ctx_aligned_size, memsize;
292
293   static const unsigned char key[16] ATTR_ALIGNED_16 = {
294       0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
295       0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21
296     };
297
298   /* Allocate buffers, align first two elements to 16 bytes and latter to
299      block size.  */
300   ctx_aligned_size = context_size + 15;
301   ctx_aligned_size -= ctx_aligned_size & 0xf;
302
303   memsize = ctx_aligned_size + (blocksize * 2) + (blocksize * nblocks * 4) + 16;
304
305   mem = xtrycalloc (1, memsize);
306   if (!mem)
307     return "failed to allocate memory";
308
309   offs = (16 - ((uintptr_t)mem & 15)) & 15;
310   ctx = (void*)(mem + offs);
311   iv = ctx + ctx_aligned_size;
312   iv2 = iv + blocksize;
313   plaintext = iv2 + blocksize;
314   plaintext2 = plaintext + nblocks * blocksize;
315   ciphertext = plaintext2 + nblocks * blocksize;
316   ciphertext2 = ciphertext + nblocks * blocksize;
317
318   /* Initialize ctx */
319   setkey_func (ctx, key, sizeof(key));
320
321   /* Test single block code path */
322   memset (iv, 0xff, blocksize);
323   for (i = 0; i < blocksize; i++)
324     plaintext[i] = i;
325
326   /* CTR manually.  */
327   encrypt_one (ctx, ciphertext, iv);
328   for (i = 0; i < blocksize; i++)
329     ciphertext[i] ^= plaintext[i];
330   for (i = blocksize; i > 0; i--)
331     {
332       iv[i-1]++;
333       if (iv[i-1])
334         break;
335     }
336
337   memset (iv2, 0xff, blocksize);
338   bulk_ctr_enc (ctx, iv2, plaintext2, ciphertext, 1);
339
340   if (memcmp (plaintext2, plaintext, blocksize))
341     {
342       xfree (mem);
343 #ifdef HAVE_SYSLOG
344       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
345               "%s-CTR-%d test failed (plaintext mismatch)", cipher,
346               blocksize * 8);
347 #endif
348       return "selftest for CTR failed - see syslog for details";
349     }
350
351   if (memcmp (iv2, iv, blocksize))
352     {
353       xfree (mem);
354 #ifdef HAVE_SYSLOG
355       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
356               "%s-CTR-%d test failed (IV mismatch)", cipher,
357               blocksize * 8);
358 #endif
359       return "selftest for CTR failed - see syslog for details";
360     }
361
362   /* Test bulk encryption with typical IV. */
363   memset(iv, 0x57, blocksize-4);
364   iv[blocksize-1] = 1;
365   iv[blocksize-2] = 0;
366   iv[blocksize-3] = 0;
367   iv[blocksize-4] = 0;
368   memset(iv2, 0x57, blocksize-4);
369   iv2[blocksize-1] = 1;
370   iv2[blocksize-2] = 0;
371   iv2[blocksize-3] = 0;
372   iv2[blocksize-4] = 0;
373
374   for (i = 0; i < blocksize * nblocks; i++)
375     plaintext2[i] = plaintext[i] = i;
376
377   /* Create CTR ciphertext manually.  */
378   for (i = 0; i < blocksize * nblocks; i+=blocksize)
379     {
380       encrypt_one (ctx, &ciphertext[i], iv);
381       for (j = 0; j < blocksize; j++)
382         ciphertext[i+j] ^= plaintext[i+j];
383       for (j = blocksize; j > 0; j--)
384         {
385           iv[j-1]++;
386           if (iv[j-1])
387             break;
388         }
389     }
390
391   bulk_ctr_enc (ctx, iv2, ciphertext2, plaintext2, nblocks);
392
393   if (memcmp (ciphertext2, ciphertext, blocksize * nblocks))
394     {
395       xfree (mem);
396 #ifdef HAVE_SYSLOG
397       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
398               "%s-CTR-%d test failed (ciphertext mismatch, bulk)", cipher,
399               blocksize * 8);
400 #endif
401       return "selftest for CTR failed - see syslog for details";
402     }
403   if (memcmp(iv2, iv, blocksize))
404     {
405       xfree (mem);
406 #ifdef HAVE_SYSLOG
407       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
408               "%s-CTR-%d test failed (IV mismatch, bulk)", cipher,
409               blocksize * 8);
410 #endif
411       return "selftest for CTR failed - see syslog for details";
412     }
413
414   /* Test parallelized code paths (check counter overflow handling) */
415   for (diff = 0; diff < nblocks; diff++) {
416     memset(iv, 0xff, blocksize);
417     iv[blocksize-1] -= diff;
418     iv[0] = iv[1] = 0;
419     iv[2] = 0x07;
420
421     for (i = 0; i < blocksize * nblocks; i++)
422       plaintext[i] = i;
423
424     /* Create CTR ciphertext manually.  */
425     for (i = 0; i < blocksize * nblocks; i+=blocksize)
426       {
427         encrypt_one (ctx, &ciphertext[i], iv);
428         for (j = 0; j < blocksize; j++)
429           ciphertext[i+j] ^= plaintext[i+j];
430         for (j = blocksize; j > 0; j--)
431           {
432             iv[j-1]++;
433             if (iv[j-1])
434               break;
435           }
436       }
437
438     /* Decrypt using bulk CTR and compare result.  */
439     memset(iv2, 0xff, blocksize);
440     iv2[blocksize-1] -= diff;
441     iv2[0] = iv2[1] = 0;
442     iv2[2] = 0x07;
443
444     bulk_ctr_enc (ctx, iv2, plaintext2, ciphertext, nblocks);
445
446     if (memcmp (plaintext2, plaintext, blocksize * nblocks))
447       {
448         xfree (mem);
449 #ifdef HAVE_SYSLOG
450         syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
451                 "%s-CTR-%d test failed (plaintext mismatch, diff: %d)", cipher,
452                 blocksize * 8, diff);
453 #endif
454         return "selftest for CTR failed - see syslog for details";
455       }
456     if (memcmp(iv2, iv, blocksize))
457       {
458         xfree (mem);
459 #ifdef HAVE_SYSLOG
460         syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
461                 "%s-CTR-%d test failed (IV mismatch, diff: %d)", cipher,
462                 blocksize * 8, diff);
463 #endif
464         return "selftest for CTR failed - see syslog for details";
465       }
466   }
467
468   xfree (mem);
469   return NULL;
470 }