* basic.c (check_aes128_cbc_cts_cipher): New function.
[libgcrypt.git] / tests / basic.c
1 /* basic.c  -  basic regression tests
2  *      Copyright (C) 2001, 2002 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 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include "../src/gcrypt.h"
26
27 static int verbose;
28 static int error_count;
29
30 static void
31 fail ( const char *format, ... )
32 {
33     va_list arg_ptr ;
34
35     va_start( arg_ptr, format ) ;
36     vfprintf (stderr, format, arg_ptr );
37     va_end(arg_ptr);
38     error_count++;
39 }
40
41 static void
42 die ( const char *format, ... )
43 {
44     va_list arg_ptr ;
45
46     va_start( arg_ptr, format ) ;
47     vfprintf (stderr, format, arg_ptr );
48     va_end(arg_ptr);
49     exit (1);
50 }
51
52 #define MAX_DATA_LEN 100
53
54 static void
55 check_aes128_cbc_cts_cipher ()
56 {
57   char key[128/8] = "chicken teriyaki";
58   char plaintext[] = "I would like the General Gau's Chicken, please, and wonton soup.";
59   struct tv {
60     char out[MAX_DATA_LEN];
61     int inlen;
62   } tv[] = {
63     {  "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
64       "\x97", 17 },
65     { "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
66       "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5", 31 },
67     { "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
68       "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84", 32 },
69     { "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
70       "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
71       "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5", 47 },
72     { "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
73       "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
74       "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8", 48 },
75     { "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
76       "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
77       "\x48\x07\xef\xe8\x36\xee\x89\xa5\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
78       "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8", 64 }
79   };
80   GCRY_CIPHER_HD hd;
81   char out[MAX_DATA_LEN];
82   int i;
83
84   hd = gcry_cipher_open (GCRY_CIPHER_AES, 
85                          GCRY_CIPHER_MODE_CBC, 
86                          GCRY_CIPHER_CBC_CTS);
87   if (!hd) {
88     fail ("aes-cbc-cts, grcy_open_cipher failed: %s\n", gcry_strerror (-1) );
89     return;
90   }
91
92   if (gcry_cipher_setkey (hd, key, 128/8)) { 
93     fail ("aes-cbc-cts, gcry_cipher_setkey failed: %s\n", gcry_strerror (-1) );
94     gcry_cipher_close (hd);
95     return;
96   }
97
98   for (i = 0; i < sizeof(tv) / sizeof(tv[0]); i++)
99     {
100       if (gcry_cipher_setiv (hd, NULL, 0)) { 
101         fail ("aes-cbc-cts, gcry_cipher_setiv failed: %s\n",
102               gcry_strerror (-1) );
103         gcry_cipher_close (hd);
104         return;
105       }
106
107       if ( gcry_cipher_encrypt (hd, out, MAX_DATA_LEN, 
108                                 plaintext, tv[i].inlen)) { 
109         fail ("aes-cbc-cts, gcry_cipher_encrypt failed: %s\n",
110               gcry_strerror (-1) );
111         gcry_cipher_close (hd);
112         return;
113       }
114
115       if ( memcmp (tv[i].out, out, tv[i].inlen) )
116         fail ("aes-cbc-cts, encrypt mismatch entry %d\n", i);
117
118       if (gcry_cipher_setiv (hd, NULL, 0)) { 
119         fail ("aes-cbc-cts, gcry_cipher_setiv failed: %s\n",
120               gcry_strerror (-1) );
121         gcry_cipher_close (hd);
122         return;
123       }
124       if ( gcry_cipher_decrypt (hd, out, tv[i].inlen, NULL, 0)) { 
125         fail ("aes-cbc-cts, gcry_cipher_decrypt failed: %s\n",
126               gcry_strerror (-1) );
127         gcry_cipher_close (hd);
128         return;
129       }
130
131       if ( memcmp (plaintext, out, tv[i].inlen) )
132         fail ("aes-cbc-cts, decrypt mismatch entry %d\n", i);
133     }
134
135   gcry_cipher_close (hd);
136 }
137
138 static void
139 check_one_cipher (int algo, int mode, int flags)
140 {
141     GCRY_CIPHER_HD hd;
142     char key[32], plain[16], in[16], out[16];
143     int keylen;
144
145     memcpy (key, "0123456789abcdef.,;/[]{}-=ABCDEF", 32);
146     memcpy (plain, "foobar42FOOBAR17", 16);
147
148     keylen = gcry_cipher_get_algo_keylen (algo);
149     if (keylen < 40/8 || keylen > 32 ) {
150         fail ("algo %d, mode %d, keylength problem (%d)\n",
151               algo, mode, keylen );
152         return;
153     }
154
155     hd = gcry_cipher_open (algo, mode, flags);
156     if (!hd) {
157         fail ("algo %d, mode %d, grcy_open_cipher failed: %s\n",
158               algo, mode, gcry_strerror (-1) );
159         return;
160     }
161
162     
163     if (gcry_cipher_setkey (hd, key, keylen)) { 
164         fail ("algo %d, mode %d, gcry_cipher_setkey failed: %s\n",
165               algo, mode, gcry_strerror (-1) );
166         gcry_cipher_close (hd);
167         return;
168     }
169     
170     if ( gcry_cipher_encrypt (hd, out, 16, plain, 16)) { 
171         fail ("algo %d, mode %d, gcry_cipher_encrypt failed: %s\n",
172               algo, mode, gcry_strerror (-1) );
173         gcry_cipher_close (hd);
174         return;
175     }
176
177     gcry_cipher_close (hd);
178     hd = gcry_cipher_open (algo, mode, flags);
179     if (!hd) {
180         fail ("algo %d, mode %d, grcy_open_cipher failed: %s\n",
181               algo, mode, gcry_strerror (-1) );
182         return;
183     }
184
185     if (gcry_cipher_setkey (hd, key, keylen)) { 
186         fail ("algo %d, mode %d, gcry_cipher_setkey[2] failed: %s\n",
187               algo, mode, gcry_strerror (-1) );
188         gcry_cipher_close (hd);
189         return;
190     }
191     
192     if ( gcry_cipher_decrypt (hd, in, 16, out, 16)) { 
193         fail ("algo %d, mode %d, gcry_cipher_decrypt failed: %s\n",
194               algo, mode, gcry_strerror (-1) );
195         gcry_cipher_close (hd);
196         return;
197     }
198
199     gcry_cipher_close (hd);
200
201     if ( memcmp (plain, in, 16) )
202         fail ("algo %d, mode %d, encrypt-decrypt mismatch\n", algo, mode);
203 }
204
205
206 static void
207 check_ciphers (void)
208 {
209   static int algos[] = {
210     GCRY_CIPHER_3DES,
211     GCRY_CIPHER_CAST5,
212     GCRY_CIPHER_BLOWFISH,
213     GCRY_CIPHER_AES,
214     GCRY_CIPHER_AES192,
215     GCRY_CIPHER_AES256,
216     GCRY_CIPHER_TWOFISH,
217     GCRY_CIPHER_DES,
218     0
219   };
220   static int algos2[] = {
221     GCRY_CIPHER_ARCFOUR,
222     0
223   };
224   int i;
225
226   for (i=0; algos[i]; i++ ) 
227     {
228       if (verbose)
229         fprintf (stderr, "checking `%s'\n", gcry_cipher_algo_name (algos[i]));
230                  
231       check_one_cipher (algos[i], GCRY_CIPHER_MODE_ECB, 0);
232       check_one_cipher (algos[i], GCRY_CIPHER_MODE_CFB, 0);
233       check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, 0);
234       check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS);
235     }
236
237   for (i=0; algos2[i]; i++ ) 
238     {
239       if (verbose)
240         fprintf (stderr, "checking `%s'\n", gcry_cipher_algo_name (algos2[i]));
241                  
242       check_one_cipher (algos2[i], GCRY_CIPHER_MODE_STREAM, 0);
243     }
244   /* we have now run all cipher's selftests */
245
246   /* TODO: add some extra encryption to test the higher level functions */
247 }
248
249 static void
250 check_one_md (int algo, char *data, int len, char *expect)
251 {
252     GCRY_MD_HD hd;
253     char *p;
254     int mdlen;
255
256     hd = gcry_md_open (algo, 0);
257     if (!hd) {
258         fail ("algo %d, grcy_md_open failed: %s\n",
259               algo, gcry_strerror (-1) );
260         return;
261     }
262
263     mdlen = gcry_md_get_algo_dlen(algo);
264     if (mdlen < 1 || mdlen > 500) {
265         fail ("algo %d, grcy_md_get_algo_dlen failed: %d\n", algo, mdlen);
266         return;
267     }
268     
269     gcry_md_write (hd, data, len);
270
271     p = gcry_md_read (hd, algo);
272
273     if ( memcmp (p, expect, mdlen) )
274         fail ("algo %d, digest mismatch\n", algo);
275
276     gcry_md_close (hd);
277 }
278
279 static void
280 check_digests ()
281 {
282   static struct algos {
283     int md;
284     char *data;
285     char *expect;
286   } algos[] = {
287     { GCRY_MD_MD4, "",
288       "\x31\xD6\xCF\xE0\xD1\x6A\xE9\x31\xB7\x3C\x59\xD7\xE0\xC0\x89\xC0" },
289     { GCRY_MD_MD4, "a",
290       "\xBD\xE5\x2C\xB3\x1D\xE3\x3E\x46\x24\x5E\x05\xFB\xDB\xD6\xFB\x24" },
291     { GCRY_MD_MD5, "",
292       "\xD4\x1D\x8C\xD9\x8F\x00\xB2\x04\xE9\x80\x09\x98\xEC\xF8\x42\x7E" },
293     { GCRY_MD_MD5, "a", 
294       "\x0C\xC1\x75\xB9\xC0\xF1\xB6\xA8\x31\xC3\x99\xE2\x69\x77\x26\x61" },
295     { GCRY_MD_MD5, "abc",
296       "\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72" },
297     { GCRY_MD_MD5, "message digest", 
298       "\xF9\x6B\x69\x7D\x7C\xB7\x93\x8D\x52\x5A\x2F\x31\xAA\xF1\x61\xD0"},
299     { GCRY_MD_SHA1, "abc",
300       "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E"
301       "\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D"},
302     { GCRY_MD_SHA1, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
303       "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE"
304       "\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1" },
305     { GCRY_MD_RMD160, "",
306       "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28"
307       "\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31" },
308     { GCRY_MD_RMD160, "a",
309       "\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae"
310       "\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe" },
311     { GCRY_MD_RMD160, "abc",
312       "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04"
313       "\x4a\x8e\x98\xc6\xb0\x87\xf1\x5a\x0b\xfc" },
314     { GCRY_MD_RMD160, "message digest",
315       "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8"
316       "\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36" },
317 #if 0
318     { GCRY_MD_TIGER, "",
319       "\x24\xF0\x13\x0C\x63\xAC\x93\x32\x16\x16\x6E\x76"
320       "\xB1\xBB\x92\x5F\xF3\x73\xDE\x2D\x49\x58\x4E\x7A" },
321     { GCRY_MD_TIGER, "abc",
322       "\xF2\x58\xC1\xE8\x84\x14\xAB\x2A\x52\x7A\xB5\x41"
323       "\xFF\xC5\xB8\xBF\x93\x5F\x7B\x95\x1C\x13\x29\x51" },
324     { GCRY_MD_TIGER, "Tiger",
325       "\x9F\x00\xF5\x99\x07\x23\x00\xDD\x27\x6A\xBB\x38"
326       "\xC8\xEB\x6D\xEC\x37\x79\x0C\x11\x6F\x9D\x2B\xDF" },
327     { GCRY_MD_TIGER, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg"
328       "hijklmnopqrstuvwxyz0123456789+-",
329       "\x87\xFB\x2A\x90\x83\x85\x1C\xF7\x47\x0D\x2C\xF8"
330       "\x10\xE6\xDF\x9E\xB5\x86\x44\x50\x34\xA5\xA3\x86" },
331     { GCRY_MD_TIGER, "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdef"
332       "ghijklmnopqrstuvwxyz+0123456789",
333       "467DB80863EBCE488DF1CD1261655DE957896565975F9197" },
334     { GCRY_MD_TIGER, "Tiger - A Fast New Hash Function, "
335       "by Ross Anderson and Eli Biham",
336       "0C410A042968868A1671DA5A3FD29A725EC1E457D3CDB303" },
337     { GCRY_MD_TIGER, "Tiger - A Fast New Hash Function, "
338       "by Ross Anderson and Eli Biham, proceedings of Fa"
339       "st Software Encryption 3, Cambridge.",
340       "EBF591D5AFA655CE7F22894FF87F54AC89C811B6B0DA3193" },
341     { GCRY_MD_TIGER, "Tiger - A Fast New Hash Function, "
342       "by Ross Anderson and Eli Biham, proceedings of Fa"
343       "st Software Encryption 3, Cambridge, 1996.",
344       "3D9AEB03D1BD1A6357B2774DFD6D5B24DD68151D503974FC" },
345     { GCRY_MD_TIGER, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh"
346       "ijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRS"
347       "TUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
348       "00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4" },
349 #endif
350     { 0 }
351   };
352   int i;
353
354   for (i=0; algos[i].md; i++ ) 
355     {
356       if (verbose)
357         fprintf (stderr, "checking `%s'\n", gcry_md_algo_name (algos[i].md));
358                  
359       check_one_md (algos[i].md, algos[i].data, strlen(algos[i].data), 
360                     algos[i].expect);
361     }
362
363   /* TODO: test HMAC mode */
364 }
365
366
367 int
368 main (int argc, char **argv)
369 {
370   if (argc > 1 && !strcmp (argv[1], "--verbose"))
371     verbose = 1;
372
373   /*gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING, NULL, 0);*/
374   if (!gcry_check_version (GCRYPT_VERSION))
375     die ("version mismatch\n");
376   check_ciphers ();
377   check_aes128_cbc_cts_cipher ();
378   check_digests ();
379   
380   return error_count? 1:0;
381 }
382
383