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