* gc-gnulib.c: Support ARCTWO in CBC mode.
[gnulib.git] / lib / gc-gnulib.c
1 /* gc-gl-common.c --- Common gnulib internal crypto interface functions
2  * Copyright (C) 2002, 2003, 2004, 2005  Simon Josefsson
3  *
4  * This file is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published
6  * by the Free Software Foundation; either version 2, or (at your
7  * option) any later version.
8  *
9  * This file is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this file; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  */
20
21 /* Note: This file is only built if GC uses internal functions. */
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 /* Get prototype. */
28 #include "gc.h"
29
30 #include <stdlib.h>
31 #include <string.h>
32
33 /* For randomize. */
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <errno.h>
39
40 /* Hashes. */
41 #ifdef GC_USE_MD4
42 # include "md4.h"
43 #endif
44 #ifdef GC_USE_MD5
45 # include "md5.h"
46 #endif
47 #ifdef GC_USE_SHA1
48 # include "sha1.h"
49 #endif
50 #ifdef GC_USE_HMAC_MD5
51 # include "hmac.h"
52 #endif
53
54 /* Ciphers. */
55 #ifdef GC_USE_ARCFOUR
56 # include "arcfour.h"
57 #endif
58 #ifdef GC_USE_ARCTWO
59 # include "arctwo.h"
60 #endif
61 #ifdef GC_USE_DES
62 # include "des.h"
63 #endif
64 #ifdef GC_USE_RIJNDAEL
65 # include "rijndael-api-fst.h"
66 #endif
67
68 Gc_rc
69 gc_init (void)
70 {
71   return GC_OK;
72 }
73
74 void
75 gc_done (void)
76 {
77   return;
78 }
79
80 /* Randomness. */
81
82 static Gc_rc
83 randomize (int level, char *data, size_t datalen)
84 {
85   int fd;
86   const char *device;
87   size_t len = 0;
88   int rc;
89
90   switch (level)
91     {
92     case 0:
93       device = NAME_OF_NONCE_DEVICE;
94       break;
95
96     case 1:
97       device = NAME_OF_PSEUDO_RANDOM_DEVICE;
98       break;
99
100     default:
101       device = NAME_OF_RANDOM_DEVICE;
102       break;
103     }
104
105   fd = open (device, O_RDONLY);
106   if (fd < 0)
107     return GC_RANDOM_ERROR;
108
109   do
110     {
111       ssize_t tmp;
112
113       tmp = read (fd, data, datalen);
114
115       if (tmp < 0)
116         {
117           int save_errno = errno;
118           close (fd);
119           errno = save_errno;
120           return GC_RANDOM_ERROR;
121         }
122
123       len += tmp;
124     }
125   while (len < datalen);
126
127   rc = close (fd);
128   if (rc < 0)
129     return GC_RANDOM_ERROR;
130
131   return GC_OK;
132 }
133
134 Gc_rc
135 gc_nonce (char *data, size_t datalen)
136 {
137   return randomize (0, data, datalen);
138 }
139
140 Gc_rc
141 gc_pseudo_random (char *data, size_t datalen)
142 {
143   return randomize (1, data, datalen);
144 }
145
146 Gc_rc
147 gc_random (char *data, size_t datalen)
148 {
149   return randomize (2, data, datalen);
150 }
151
152 /* Memory allocation. */
153
154 void
155 gc_set_allocators (gc_malloc_t func_malloc,
156                    gc_malloc_t secure_malloc,
157                    gc_secure_check_t secure_check,
158                    gc_realloc_t func_realloc, gc_free_t func_free)
159 {
160   return;
161 }
162 /* Ciphers. */
163
164 typedef struct _gc_cipher_ctx {
165   Gc_cipher alg;
166   Gc_cipher_mode mode;
167 #ifdef GC_USE_ARCTWO
168   arctwo_context arctwoContext;
169   char arctwoIV[ARCTWO_BLOCK_SIZE];
170 #endif
171 #ifdef GC_USE_ARCFOUR
172   arcfour_context arcfourContext;
173 #endif
174 #ifdef GC_USE_DES
175   des_ctx desContext;
176 #endif
177 #ifdef GC_USE_RIJNDAEL
178   rijndaelKeyInstance aesEncKey;
179   rijndaelKeyInstance aesDecKey;
180   rijndaelCipherInstance aesContext;
181 #endif
182 } _gc_cipher_ctx;
183
184 Gc_rc
185 gc_cipher_open (Gc_cipher alg, Gc_cipher_mode mode,
186                 gc_cipher_handle * outhandle)
187 {
188   _gc_cipher_ctx *ctx;
189   Gc_rc rc = GC_OK;
190
191   ctx = calloc (sizeof (*ctx), 1);
192
193   ctx->alg = alg;
194   ctx->mode = mode;
195
196   switch (alg)
197     {
198 #ifdef GC_USE_ARCTWO
199     case GC_ARCTWO40:
200       switch (mode)
201         {
202         case GC_ECB:
203         case GC_CBC:
204           break;
205
206         default:
207           rc = GC_INVALID_CIPHER;
208         }
209       break;
210 #endif
211
212 #ifdef GC_USE_ARCFOUR
213     case GC_ARCFOUR128:
214     case GC_ARCFOUR40:
215       switch (mode)
216         {
217         case GC_STREAM:
218           break;
219
220         default:
221           rc = GC_INVALID_CIPHER;
222         }
223       break;
224 #endif
225
226 #ifdef GC_USE_DES
227     case GC_DES:
228       switch (mode)
229         {
230         case GC_ECB:
231           break;
232
233         default:
234           rc = GC_INVALID_CIPHER;
235         }
236       break;
237 #endif
238
239 #ifdef GC_USE_RIJNDAEL
240     case GC_AES128:
241     case GC_AES192:
242     case GC_AES256:
243       switch (mode)
244         {
245         case GC_ECB:
246         case GC_CBC:
247           break;
248
249         default:
250           rc = GC_INVALID_CIPHER;
251         }
252       break;
253 #endif
254
255     default:
256       rc = GC_INVALID_CIPHER;
257     }
258
259   if (rc == GC_OK)
260     *outhandle = ctx;
261   else
262     free (ctx);
263
264   return rc;
265 }
266
267 Gc_rc
268 gc_cipher_setkey (gc_cipher_handle handle, size_t keylen, const char *key)
269 {
270   _gc_cipher_ctx *ctx = handle;
271
272   switch (ctx->alg)
273     {
274 #ifdef GC_USE_ARCTWO
275     case GC_ARCTWO40:
276       arctwo_setkey (&ctx->arctwoContext, keylen, key);
277       break;
278 #endif
279
280 #ifdef GC_USE_ARCFOUR
281     case GC_ARCFOUR128:
282     case GC_ARCFOUR40:
283       arcfour_setkey (&ctx->arcfourContext, key, keylen);
284       break;
285 #endif
286
287 #ifdef GC_USE_DES
288     case GC_DES:
289       if (keylen != 8)
290         return GC_INVALID_CIPHER;
291       des_setkey (&ctx->desContext, key);
292       break;
293 #endif
294
295 #ifdef GC_USE_RIJNDAEL
296     case GC_AES128:
297     case GC_AES192:
298     case GC_AES256:
299       {
300         rijndael_rc rc;
301         size_t i;
302         char keyMaterial[RIJNDAEL_MAX_KEY_SIZE + 1];
303
304         for (i = 0; i < keylen; i++)
305           sprintf (&keyMaterial[2*i], "%02x", key[i] & 0xFF);
306
307         rc = rijndaelMakeKey (&ctx->aesEncKey, RIJNDAEL_DIR_ENCRYPT,
308                               keylen * 8, keyMaterial);
309         if (rc < 0)
310           return GC_INVALID_CIPHER;
311
312         rc = rijndaelMakeKey (&ctx->aesDecKey, RIJNDAEL_DIR_DECRYPT,
313                               keylen * 8, keyMaterial);
314         if (rc < 0)
315           return GC_INVALID_CIPHER;
316
317         rc = rijndaelCipherInit (&ctx->aesContext, RIJNDAEL_MODE_ECB, NULL);
318         if (rc < 0)
319           return GC_INVALID_CIPHER;
320       }
321       break;
322 #endif
323
324     default:
325       return GC_INVALID_CIPHER;
326     }
327
328   return GC_OK;
329 }
330
331 Gc_rc
332 gc_cipher_setiv (gc_cipher_handle handle, size_t ivlen, const char *iv)
333 {
334   _gc_cipher_ctx *ctx = handle;
335
336   switch (ctx->alg)
337     {
338 #ifdef GC_USE_ARCTWO
339     case GC_ARCTWO40:
340       if (ivlen != ARCTWO_BLOCK_SIZE)
341         return GC_INVALID_CIPHER;
342       memcpy (ctx->arctwoIV, iv, ivlen);
343       break;
344 #endif
345
346 #ifdef GC_USE_RIJNDAEL
347     case GC_AES128:
348     case GC_AES192:
349     case GC_AES256:
350       switch (ctx->mode)
351         {
352         case GC_ECB:
353           /* Doesn't use IV. */
354           break;
355
356         case GC_CBC:
357           {
358             rijndael_rc rc;
359             size_t i;
360             char ivMaterial[2 * RIJNDAEL_MAX_IV_SIZE + 1];
361
362             for (i = 0; i < ivlen; i++)
363               sprintf (&ivMaterial[2*i], "%02x", iv[i] & 0xFF);
364
365             rc = rijndaelCipherInit (&ctx->aesContext, RIJNDAEL_MODE_CBC,
366                                      ivMaterial);
367             if (rc < 0)
368               return GC_INVALID_CIPHER;
369           }
370           break;
371
372         default:
373           return GC_INVALID_CIPHER;
374         }
375       break;
376 #endif
377
378     default:
379       return GC_INVALID_CIPHER;
380     }
381
382   return GC_OK;
383 }
384
385 Gc_rc
386 gc_cipher_encrypt_inline (gc_cipher_handle handle, size_t len, char *data)
387 {
388   _gc_cipher_ctx *ctx = handle;
389
390   switch (ctx->alg)
391     {
392 #ifdef GC_USE_ARCTWO
393     case GC_ARCTWO40:
394       switch (ctx->mode)
395         {
396         case GC_ECB:
397           arctwo_encrypt (&ctx->arctwoContext, data, data, len);
398           break;
399
400         case GC_CBC:
401           for (; len >= ARCTWO_BLOCK_SIZE; len -= ARCTWO_BLOCK_SIZE,
402                  data += ARCTWO_BLOCK_SIZE)
403             {
404               size_t i;
405               for (i = 0; i < ARCTWO_BLOCK_SIZE; i++)
406                 data[i] ^= ctx->arctwoIV[i];
407               arctwo_encrypt (&ctx->arctwoContext, data, data,
408                               ARCTWO_BLOCK_SIZE);
409               memcpy (ctx->arctwoIV, data, ARCTWO_BLOCK_SIZE);
410             }
411             break;
412
413         default:
414           return GC_INVALID_CIPHER;
415         }
416       break;
417 #endif
418
419 #ifdef GC_USE_ARCFOUR
420     case GC_ARCFOUR128:
421     case GC_ARCFOUR40:
422       arcfour_stream (&ctx->arcfourContext, data, data, len);
423       break;
424 #endif
425
426 #ifdef GC_USE_DES
427     case GC_DES:
428       for (; len >= 8; len -= 8, data += 8)
429         des_ecb_encrypt (&ctx->desContext, data, data);
430       break;
431 #endif
432
433 #ifdef GC_USE_RIJNDAEL
434     case GC_AES128:
435     case GC_AES192:
436     case GC_AES256:
437       {
438         int nblocks;
439
440         nblocks = rijndaelBlockEncrypt (&ctx->aesContext, &ctx->aesEncKey,
441                                         data, 8 * len, data);
442         if (nblocks < 0)
443           return GC_INVALID_CIPHER;
444       }
445       break;
446 #endif
447
448     default:
449       return GC_INVALID_CIPHER;
450     }
451
452   return GC_OK;
453 }
454
455 Gc_rc
456 gc_cipher_decrypt_inline (gc_cipher_handle handle, size_t len, char *data)
457 {
458   _gc_cipher_ctx *ctx = handle;
459
460   switch (ctx->alg)
461     {
462 #ifdef GC_USE_ARCTWO
463     case GC_ARCTWO40:
464       switch (ctx->mode)
465         {
466         case GC_ECB:
467           arctwo_decrypt (&ctx->arctwoContext, data, data, len);
468           break;
469
470         case GC_CBC:
471           for (; len >= ARCTWO_BLOCK_SIZE; len -= ARCTWO_BLOCK_SIZE,
472                  data += ARCTWO_BLOCK_SIZE)
473             {
474               char tmpIV[ARCTWO_BLOCK_SIZE];
475               size_t i;
476               memcpy (tmpIV, data, ARCTWO_BLOCK_SIZE);
477               arctwo_decrypt (&ctx->arctwoContext, data, data,
478                               ARCTWO_BLOCK_SIZE);
479               for (i = 0; i < ARCTWO_BLOCK_SIZE; i++)
480                 data[i] ^= ctx->arctwoIV[i];
481               memcpy (ctx->arctwoIV, tmpIV, ARCTWO_BLOCK_SIZE);
482             }
483           break;
484
485         default:
486           return GC_INVALID_CIPHER;
487         }
488       break;
489 #endif
490
491 #ifdef GC_USE_ARCFOUR
492     case GC_ARCFOUR128:
493     case GC_ARCFOUR40:
494       arcfour_stream (&ctx->arcfourContext, data, data, len);
495       break;
496 #endif
497
498 #ifdef GC_USE_DES
499     case GC_DES:
500       for (; len >= 8; len -= 8, data += 8)
501         des_ecb_decrypt (&ctx->desContext, data, data);
502       break;
503 #endif
504
505 #ifdef GC_USE_RIJNDAEL
506     case GC_AES128:
507     case GC_AES192:
508     case GC_AES256:
509       {
510         int nblocks;
511
512         nblocks = rijndaelBlockDecrypt (&ctx->aesContext, &ctx->aesDecKey,
513                                         data, 8 * len, data);
514         if (nblocks < 0)
515           return GC_INVALID_CIPHER;
516       }
517       break;
518 #endif
519
520     default:
521       return GC_INVALID_CIPHER;
522     }
523
524   return GC_OK;
525 }
526
527 Gc_rc
528 gc_cipher_close (gc_cipher_handle handle)
529 {
530   _gc_cipher_ctx *ctx = handle;
531
532   if (ctx)
533     free (ctx);
534
535   return GC_OK;
536 }
537
538 /* Hashes. */
539
540 Gc_rc
541 gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
542 {
543   switch (hash)
544     {
545 #ifdef GC_USE_MD4
546     case GC_MD4:
547       md4_buffer (in, inlen, resbuf);
548       break;
549 #endif
550
551 #ifdef GC_USE_MD5
552     case GC_MD5:
553       md5_buffer (in, inlen, resbuf);
554       break;
555 #endif
556
557 #ifdef GC_USE_SHA1
558     case GC_SHA1:
559       sha1_buffer (in, inlen, resbuf);
560       break;
561 #endif
562
563     default:
564       return GC_INVALID_HASH;
565     }
566
567   return GC_OK;
568 }
569
570 #ifdef GC_USE_MD4
571 Gc_rc
572 gc_md4 (const void *in, size_t inlen, void *resbuf)
573 {
574   md4_buffer (in, inlen, resbuf);
575   return GC_OK;
576 }
577 #endif
578
579 #ifdef GC_USE_MD5
580 Gc_rc
581 gc_md5 (const void *in, size_t inlen, void *resbuf)
582 {
583   md5_buffer (in, inlen, resbuf);
584   return GC_OK;
585 }
586 #endif
587
588 #ifdef GC_USE_SHA1
589 Gc_rc
590 gc_sha1 (const void *in, size_t inlen, void *resbuf)
591 {
592   sha1_buffer (in, inlen, resbuf);
593   return GC_OK;
594 }
595 #endif
596
597 #ifdef GC_USE_HMAC_MD5
598 Gc_rc
599 gc_hmac_md5 (const void *key, size_t keylen,
600              const void *in, size_t inlen, char *resbuf)
601 {
602   hmac_md5 (key, keylen, in, inlen, resbuf);
603   return GC_OK;
604 }
605 #endif
606
607 #ifdef GC_USE_HMAC_SHA1
608 Gc_rc
609 gc_hmac_sha1 (const void *key, size_t keylen,
610               const void *in, size_t inlen, char *resbuf)
611 {
612   hmac_sha1 (key, keylen, in, inlen, resbuf);
613   return GC_OK;
614 }
615 #endif