Add gc-arcfour and gc-arcfour-tests modules.
[pspp] / 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_RIJNDAEL
59 # include "rijndael-api-fst.h"
60 #endif
61
62 Gc_rc
63 gc_init (void)
64 {
65   return GC_OK;
66 }
67
68 void
69 gc_done (void)
70 {
71   return;
72 }
73
74 /* Randomness. */
75
76 static Gc_rc
77 randomize (int level, char *data, size_t datalen)
78 {
79   int fd;
80   const char *device;
81   size_t len = 0;
82   int rc;
83
84   switch (level)
85     {
86     case 0:
87       device = NAME_OF_NONCE_DEVICE;
88       break;
89
90     case 1:
91       device = NAME_OF_PSEUDO_RANDOM_DEVICE;
92       break;
93
94     default:
95       device = NAME_OF_RANDOM_DEVICE;
96       break;
97     }
98
99   fd = open (device, O_RDONLY);
100   if (fd < 0)
101     return GC_RANDOM_ERROR;
102
103   do
104     {
105       ssize_t tmp;
106
107       tmp = read (fd, data, datalen);
108
109       if (tmp < 0)
110         {
111           int save_errno = errno;
112           close (fd);
113           errno = save_errno;
114           return GC_RANDOM_ERROR;
115         }
116
117       len += tmp;
118     }
119   while (len < datalen);
120
121   rc = close (fd);
122   if (rc < 0)
123     return GC_RANDOM_ERROR;
124
125   return GC_OK;
126 }
127
128 Gc_rc
129 gc_nonce (char *data, size_t datalen)
130 {
131   return randomize (0, data, datalen);
132 }
133
134 Gc_rc
135 gc_pseudo_random (char *data, size_t datalen)
136 {
137   return randomize (1, data, datalen);
138 }
139
140 Gc_rc
141 gc_random (char *data, size_t datalen)
142 {
143   return randomize (2, data, datalen);
144 }
145
146 /* Memory allocation. */
147
148 void
149 gc_set_allocators (gc_malloc_t func_malloc,
150                    gc_malloc_t secure_malloc,
151                    gc_secure_check_t secure_check,
152                    gc_realloc_t func_realloc, gc_free_t func_free)
153 {
154   return;
155 }
156 /* Ciphers. */
157
158 typedef struct _gc_cipher_ctx {
159   Gc_cipher alg;
160   Gc_cipher_mode mode;
161 #ifdef GC_USE_ARCFOUR
162   arcfour_context arcfourContext;
163 #endif
164 #ifdef GC_USE_RIJNDAEL
165   rijndaelKeyInstance aesEncKey;
166   rijndaelKeyInstance aesDecKey;
167   rijndaelCipherInstance aesContext;
168 #endif
169 } _gc_cipher_ctx;
170
171 Gc_rc
172 gc_cipher_open (Gc_cipher alg, Gc_cipher_mode mode,
173                 gc_cipher_handle * outhandle)
174 {
175   _gc_cipher_ctx *ctx;
176   Gc_rc rc = GC_OK;
177
178   ctx = calloc (sizeof (*ctx), 1);
179
180   ctx->alg = alg;
181   ctx->mode = mode;
182
183   switch (alg)
184     {
185 #ifdef GC_USE_ARCFOUR
186     case GC_ARCFOUR128:
187     case GC_ARCFOUR40:
188       switch (mode)
189         {
190         case GC_STREAM:
191           break;
192
193         default:
194           rc = GC_INVALID_CIPHER;
195         }
196       break;
197 #endif
198
199 #ifdef GC_USE_RIJNDAEL
200     case GC_AES128:
201     case GC_AES192:
202     case GC_AES256:
203       switch (mode)
204         {
205         case GC_ECB:
206         case GC_CBC:
207           break;
208
209         default:
210           rc = GC_INVALID_CIPHER;
211         }
212       break;
213 #endif
214
215     default:
216       rc = GC_INVALID_CIPHER;
217     }
218
219   if (rc == GC_OK)
220     *outhandle = ctx;
221   else
222     free (ctx);
223
224   return rc;
225 }
226
227 Gc_rc
228 gc_cipher_setkey (gc_cipher_handle handle, size_t keylen, const char *key)
229 {
230   _gc_cipher_ctx *ctx = handle;
231
232   switch (ctx->alg)
233     {
234 #ifdef GC_USE_ARCFOUR
235     case GC_ARCFOUR128:
236     case GC_ARCFOUR40:
237       arcfour_setkey (&ctx->arcfourContext, key, keylen);
238       break;
239 #endif
240
241 #ifdef GC_USE_RIJNDAEL
242     case GC_AES128:
243     case GC_AES192:
244     case GC_AES256:
245       {
246         rijndael_rc rc;
247         size_t i;
248         char keyMaterial[RIJNDAEL_MAX_KEY_SIZE + 1];
249
250         for (i = 0; i < keylen; i++)
251           sprintf (&keyMaterial[2*i], "%02x", key[i] & 0xFF);
252
253         rc = rijndaelMakeKey (&ctx->aesEncKey, RIJNDAEL_DIR_ENCRYPT,
254                               keylen * 8, keyMaterial);
255         if (rc < 0)
256           return GC_INVALID_CIPHER;
257
258         rc = rijndaelMakeKey (&ctx->aesDecKey, RIJNDAEL_DIR_DECRYPT,
259                               keylen * 8, keyMaterial);
260         if (rc < 0)
261           return GC_INVALID_CIPHER;
262
263         rc = rijndaelCipherInit (&ctx->aesContext, RIJNDAEL_MODE_ECB, NULL);
264         if (rc < 0)
265           return GC_INVALID_CIPHER;
266       }
267       break;
268 #endif
269
270     default:
271       return GC_INVALID_CIPHER;
272     }
273
274   return GC_OK;
275 }
276
277 Gc_rc
278 gc_cipher_setiv (gc_cipher_handle handle, size_t ivlen, const char *iv)
279 {
280   _gc_cipher_ctx *ctx = handle;
281
282   switch (ctx->alg)
283     {
284 #ifdef GC_USE_RIJNDAEL
285     case GC_AES128:
286     case GC_AES192:
287     case GC_AES256:
288       switch (ctx->mode)
289         {
290         case GC_ECB:
291           /* Doesn't use IV. */
292           break;
293
294         case GC_CBC:
295           {
296             rijndael_rc rc;
297             size_t i;
298             char ivMaterial[2 * RIJNDAEL_MAX_IV_SIZE + 1];
299
300             for (i = 0; i < ivlen; i++)
301               sprintf (&ivMaterial[2*i], "%02x", iv[i] & 0xFF);
302
303             rc = rijndaelCipherInit (&ctx->aesContext, RIJNDAEL_MODE_CBC,
304                                      ivMaterial);
305             if (rc < 0)
306               return GC_INVALID_CIPHER;
307           }
308           break;
309
310         default:
311           return GC_INVALID_CIPHER;
312         }
313       break;
314 #endif
315
316     default:
317       return GC_INVALID_CIPHER;
318     }
319
320   return GC_OK;
321 }
322
323 Gc_rc
324 gc_cipher_encrypt_inline (gc_cipher_handle handle, size_t len, char *data)
325 {
326   _gc_cipher_ctx *ctx = handle;
327
328   switch (ctx->alg)
329     {
330 #ifdef GC_USE_ARCFOUR
331     case GC_ARCFOUR128:
332     case GC_ARCFOUR40:
333       arcfour_stream (&ctx->arcfourContext, data, data, len);
334       break;
335 #endif
336
337 #ifdef GC_USE_RIJNDAEL
338     case GC_AES128:
339     case GC_AES192:
340     case GC_AES256:
341       {
342         int nblocks;
343
344         nblocks = rijndaelBlockEncrypt (&ctx->aesContext, &ctx->aesEncKey,
345                                         data, 8 * len, data);
346         if (nblocks < 0)
347           return GC_INVALID_CIPHER;
348       }
349       break;
350 #endif
351
352     default:
353       return GC_INVALID_CIPHER;
354     }
355
356   return GC_OK;
357 }
358
359 Gc_rc
360 gc_cipher_decrypt_inline (gc_cipher_handle handle, size_t len, char *data)
361 {
362   _gc_cipher_ctx *ctx = handle;
363
364   switch (ctx->alg)
365     {
366 #ifdef GC_USE_ARCFOUR
367     case GC_ARCFOUR128:
368     case GC_ARCFOUR40:
369       arcfour_stream (&ctx->arcfourContext, data, data, len);
370       break;
371 #endif
372
373 #ifdef GC_USE_RIJNDAEL
374     case GC_AES128:
375     case GC_AES192:
376     case GC_AES256:
377       {
378         int nblocks;
379
380         nblocks = rijndaelBlockDecrypt (&ctx->aesContext, &ctx->aesDecKey,
381                                         data, 8 * len, data);
382         if (nblocks < 0)
383           return GC_INVALID_CIPHER;
384       }
385       break;
386 #endif
387
388     default:
389       return GC_INVALID_CIPHER;
390     }
391
392   return GC_OK;
393 }
394
395 Gc_rc
396 gc_cipher_close (gc_cipher_handle handle)
397 {
398   _gc_cipher_ctx *ctx = handle;
399
400   if (ctx)
401     free (ctx);
402
403   return GC_OK;
404 }
405
406 /* Hashes. */
407
408 Gc_rc
409 gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
410 {
411   switch (hash)
412     {
413 #ifdef GC_USE_MD4
414     case GC_MD4:
415       md4_buffer (in, inlen, resbuf);
416       break;
417 #endif
418
419 #ifdef GC_USE_MD5
420     case GC_MD5:
421       md5_buffer (in, inlen, resbuf);
422       break;
423 #endif
424
425 #ifdef GC_USE_SHA1
426     case GC_SHA1:
427       sha1_buffer (in, inlen, resbuf);
428       break;
429 #endif
430
431     default:
432       return GC_INVALID_HASH;
433     }
434
435   return GC_OK;
436 }
437
438 #ifdef GC_USE_MD4
439 Gc_rc
440 gc_md4 (const void *in, size_t inlen, void *resbuf)
441 {
442   md4_buffer (in, inlen, resbuf);
443   return GC_OK;
444 }
445 #endif
446
447 #ifdef GC_USE_MD5
448 Gc_rc
449 gc_md5 (const void *in, size_t inlen, void *resbuf)
450 {
451   md5_buffer (in, inlen, resbuf);
452   return GC_OK;
453 }
454 #endif
455
456 #ifdef GC_USE_SHA1
457 Gc_rc
458 gc_sha1 (const void *in, size_t inlen, void *resbuf)
459 {
460   sha1_buffer (in, inlen, resbuf);
461   return GC_OK;
462 }
463 #endif
464
465 #ifdef GC_USE_HMAC_MD5
466 Gc_rc
467 gc_hmac_md5 (const void *key, size_t keylen,
468              const void *in, size_t inlen, char *resbuf)
469 {
470   hmac_md5 (key, keylen, in, inlen, resbuf);
471   return GC_OK;
472 }
473 #endif
474
475 #ifdef GC_USE_HMAC_SHA1
476 Gc_rc
477 gc_hmac_sha1 (const void *key, size_t keylen,
478               const void *in, size_t inlen, char *resbuf)
479 {
480   hmac_sha1 (key, keylen, in, inlen, resbuf);
481   return GC_OK;
482 }
483 #endif