Add MD2 and hash fixes.
[pspp] / lib / gc-libgcrypt.c
1 /* gc-libgcrypt.c --- Crypto wrappers around Libgcrypt for GC.
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 Libgcrypt. */
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 /* Get libgcrypt API. */
34 #include <gcrypt.h>
35 #ifdef GC_USE_MD2
36 # include "md2.h"
37 #endif
38
39 #include <assert.h>
40
41 /* Initialization. */
42
43 Gc_rc
44 gc_init (void)
45 {
46   gcry_error_t err;
47
48   err = gcry_control (GCRYCTL_ANY_INITIALIZATION_P);
49   if (err == GPG_ERR_NO_ERROR)
50     {
51       if (gcry_check_version (GCRYPT_VERSION) == NULL)
52         return GC_INIT_ERROR;
53
54       err = gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0);
55       if (err != GPG_ERR_NO_ERROR)
56         return GC_INIT_ERROR;
57     }
58
59   return GC_OK;
60 }
61
62 void
63 gc_done (void)
64 {
65   return;
66 }
67
68 /* Randomness. */
69
70 Gc_rc
71 gc_nonce (char *data, size_t datalen)
72 {
73   gcry_create_nonce ((unsigned char *) data, datalen);
74   return GC_OK;
75 }
76
77 Gc_rc
78 gc_pseudo_random (char *data, size_t datalen)
79 {
80   gcry_randomize ((unsigned char *) data, datalen, GCRY_STRONG_RANDOM);
81   return GC_OK;
82 }
83
84 Gc_rc
85 gc_random (char *data, size_t datalen)
86 {
87   gcry_randomize ((unsigned char *) data, datalen, GCRY_VERY_STRONG_RANDOM);
88   return GC_OK;
89 }
90
91 /* Memory allocation. */
92
93 void
94 gc_set_allocators (gc_malloc_t func_malloc,
95                    gc_malloc_t secure_malloc,
96                    gc_secure_check_t secure_check,
97                    gc_realloc_t func_realloc, gc_free_t func_free)
98 {
99   gcry_set_allocation_handler (func_malloc, secure_malloc, secure_check,
100                                func_realloc, func_free);
101 }
102
103 /* Ciphers. */
104
105 Gc_rc
106 gc_cipher_open (Gc_cipher alg, Gc_cipher_mode mode,
107                 gc_cipher_handle * outhandle)
108 {
109   int gcryalg, gcrymode;
110   gcry_error_t err;
111
112   switch (alg)
113     {
114     case GC_AES128:
115       gcryalg = GCRY_CIPHER_RIJNDAEL;
116       break;
117
118     case GC_AES192:
119       gcryalg = GCRY_CIPHER_RIJNDAEL;
120       break;
121
122     case GC_AES256:
123       gcryalg = GCRY_CIPHER_RIJNDAEL256;
124       break;
125
126     case GC_3DES:
127       gcryalg = GCRY_CIPHER_3DES;
128       break;
129
130     case GC_DES:
131       gcryalg = GCRY_CIPHER_DES;
132       break;
133
134     case GC_ARCFOUR128:
135     case GC_ARCFOUR40:
136       gcryalg = GCRY_CIPHER_ARCFOUR;
137       break;
138
139     case GC_ARCTWO40:
140       gcryalg = GCRY_CIPHER_RFC2268_40;
141       break;
142
143     default:
144       return GC_INVALID_CIPHER;
145     }
146
147   switch (mode)
148     {
149     case GC_ECB:
150       gcrymode = GCRY_CIPHER_MODE_ECB;
151       break;
152
153     case GC_CBC:
154       gcrymode = GCRY_CIPHER_MODE_CBC;
155       break;
156
157     case GC_STREAM:
158       gcrymode = GCRY_CIPHER_MODE_STREAM;
159       break;
160
161     default:
162       return GC_INVALID_CIPHER;
163     }
164
165   err = gcry_cipher_open ((gcry_cipher_hd_t *) outhandle,
166                           gcryalg, gcrymode, 0);
167   if (gcry_err_code (err))
168     return GC_INVALID_CIPHER;
169
170   return GC_OK;
171 }
172
173 Gc_rc
174 gc_cipher_setkey (gc_cipher_handle handle, size_t keylen, const char *key)
175 {
176   gcry_error_t err;
177
178   err = gcry_cipher_setkey ((gcry_cipher_hd_t) handle, key, keylen);
179   if (gcry_err_code (err))
180     return GC_INVALID_CIPHER;
181
182   return GC_OK;
183 }
184
185 Gc_rc
186 gc_cipher_setiv (gc_cipher_handle handle, size_t ivlen, const char *iv)
187 {
188   gcry_error_t err;
189
190   err = gcry_cipher_setiv ((gcry_cipher_hd_t) handle, iv, ivlen);
191   if (gcry_err_code (err))
192     return GC_INVALID_CIPHER;
193
194   return GC_OK;
195 }
196
197 Gc_rc
198 gc_cipher_encrypt_inline (gc_cipher_handle handle, size_t len, char *data)
199 {
200   if (gcry_cipher_encrypt ((gcry_cipher_hd_t) handle,
201                            data, len, NULL, len) != 0)
202     return GC_INVALID_CIPHER;
203
204   return GC_OK;
205 }
206
207 Gc_rc
208 gc_cipher_decrypt_inline (gc_cipher_handle handle, size_t len, char *data)
209 {
210   if (gcry_cipher_decrypt ((gcry_cipher_hd_t) handle,
211                            data, len, NULL, len) != 0)
212     return GC_INVALID_CIPHER;
213
214   return GC_OK;
215 }
216
217 Gc_rc
218 gc_cipher_close (gc_cipher_handle handle)
219 {
220   gcry_cipher_close (handle);
221
222   return GC_OK;
223 }
224
225 /* Hashes. */
226
227 typedef struct _gc_hash_ctx {
228   Gc_hash alg;
229   Gc_hash_mode mode;
230   gcry_md_hd_t gch;
231 #ifdef GC_USE_MD2
232   char hash[GC_MD2_DIGEST_SIZE];
233   struct md2_ctx md2Context;
234 #endif
235 } _gc_hash_ctx;
236
237 Gc_rc
238 gc_hash_open (Gc_hash hash, Gc_hash_mode mode, gc_hash_handle * outhandle)
239 {
240   _gc_hash_ctx *ctx;
241   int gcryalg, gcrymode;
242   gcry_error_t err;
243   Gc_rc rc = GC_OK;
244
245   ctx = calloc (sizeof (*ctx), 1);
246
247   ctx->alg = hash;
248   ctx->mode = mode;
249
250   switch (hash)
251     {
252     case GC_MD2:
253       gcryalg = GCRY_MD_NONE;
254       break;
255
256     case GC_MD4:
257       gcryalg = GCRY_MD_MD4;
258       break;
259
260     case GC_MD5:
261       gcryalg = GCRY_MD_MD5;
262       break;
263
264     case GC_SHA1:
265       gcryalg = GCRY_MD_SHA1;
266       break;
267
268     case GC_RMD160:
269       gcryalg = GCRY_MD_RMD160;
270       break;
271
272     default:
273       rc = GC_INVALID_HASH;
274     }
275
276   switch (mode)
277     {
278     case 0:
279       gcrymode = 0;
280       break;
281
282     case GC_HMAC:
283       gcrymode = GCRY_MD_FLAG_HMAC;
284       break;
285
286     default:
287       rc = GC_INVALID_HASH;
288     }
289
290   if (rc == GC_OK && gcryalg != GCRY_MD_NONE)
291     {
292       err = gcry_md_open (&ctx->gch, gcryalg, gcrymode);
293       if (gcry_err_code (err))
294         rc = GC_INVALID_HASH;
295     }
296
297   if (rc == GC_OK)
298     *outhandle = ctx;
299   else
300     free (ctx);
301
302   return rc;
303 }
304
305 Gc_rc
306 gc_hash_clone (gc_hash_handle handle, gc_hash_handle * outhandle)
307 {
308   _gc_hash_ctx *in = handle;
309   _gc_hash_ctx *out;
310   int err;
311
312   *outhandle = out = calloc (sizeof (*out), 1);
313   if (!out)
314     return GC_MALLOC_ERROR;
315
316   memcpy (out, in, sizeof (*out));
317
318   err = gcry_md_copy (&out->gch, in->gch);
319   if (err)
320     {
321       free (out);
322       return GC_INVALID_HASH;
323     }
324
325   return GC_OK;
326 }
327
328 size_t
329 gc_hash_digest_length (Gc_hash hash)
330 {
331   size_t len;
332
333   switch (hash)
334     {
335     case GC_MD2:
336       len = GC_MD2_DIGEST_SIZE;
337       break;
338
339     case GC_MD4:
340       len = GC_MD4_DIGEST_SIZE;
341       break;
342
343     case GC_MD5:
344       len = GC_MD5_DIGEST_SIZE;
345       break;
346
347     case GC_RMD160:
348       len = GC_RMD160_DIGEST_SIZE;
349       break;
350
351     case GC_SHA1:
352       len = GC_SHA1_DIGEST_SIZE;
353       break;
354
355     default:
356       return 0;
357     }
358
359   return len;
360 }
361
362 void
363 gc_hash_hmac_setkey (gc_hash_handle handle, size_t len, const char *key)
364 {
365   _gc_hash_ctx *ctx = handle;
366 #ifdef GC_USE_MD2
367   if (ctx->alg != GC_MD2)
368 #endif
369     gcry_md_setkey (ctx->gch, key, len);
370 }
371
372 void
373 gc_hash_write (gc_hash_handle handle, size_t len, const char *data)
374 {
375   _gc_hash_ctx *ctx = handle;
376
377 #ifdef GC_USE_MD2
378   if (ctx->alg == GC_MD2)
379     md2_process_bytes (data, len, &ctx->md2Context);
380   else
381 #endif
382     gcry_md_write (ctx->gch, data, len);
383 }
384
385 const char *
386 gc_hash_read (gc_hash_handle handle)
387 {
388   _gc_hash_ctx *ctx = handle;
389   const char *digest;
390
391 #ifdef GC_USE_MD2
392   if (ctx->alg == GC_MD2)
393     {
394       md2_finish_ctx (&ctx->md2Context, ctx->hash);
395       digest = ctx->hash;
396     }
397   else
398 #endif
399     {
400       gcry_md_final (ctx->gch);
401       digest = gcry_md_read (ctx->gch, 0);
402     }
403
404   return digest;
405 }
406
407 void
408 gc_hash_close (gc_hash_handle handle)
409 {
410   _gc_hash_ctx *ctx = handle;
411
412 #ifdef GC_USE_MD2
413   if (ctx->alg != GC_MD2)
414 #endif
415     gcry_md_close (ctx->gch);
416
417   free (ctx);
418 }
419
420 Gc_rc
421 gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
422 {
423   int gcryalg;
424
425   switch (hash)
426     {
427 #ifdef GC_USE_MD2
428     case GC_MD2:
429       md2_buffer (in, inlen, resbuf);
430       return GC_OK;
431       break;
432 #endif
433
434 #ifdef GC_USE_MD4
435     case GC_MD4:
436       gcryalg = GCRY_MD_MD4;
437       break;
438 #endif
439
440 #ifdef GC_USE_MD5
441     case GC_MD5:
442       gcryalg = GCRY_MD_MD5;
443       break;
444 #endif
445
446 #ifdef GC_USE_SHA1
447     case GC_SHA1:
448       gcryalg = GCRY_MD_SHA1;
449       break;
450 #endif
451
452 #ifdef GC_USE_RMD160
453     case GC_RMD160:
454       gcryalg = GCRY_MD_RMD160;
455       break;
456 #endif
457
458     default:
459       return GC_INVALID_HASH;
460     }
461
462   gcry_md_hash_buffer (gcryalg, resbuf, in, inlen);
463
464   return GC_OK;
465 }
466
467 /* One-call interface. */
468
469 #ifdef GC_USE_MD2
470 Gc_rc
471 gc_md2 (const void *in, size_t inlen, void *resbuf)
472 {
473   md2_buffer (in, inlen, resbuf);
474   return GC_OK;
475 }
476 #endif
477
478 #ifdef GC_USE_MD4
479 Gc_rc
480 gc_md4 (const void *in, size_t inlen, void *resbuf)
481 {
482   size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_MD4);
483   gcry_md_hd_t hd;
484   gpg_error_t err;
485   unsigned char *p;
486
487   assert (outlen == GC_MD4_DIGEST_SIZE);
488
489   err = gcry_md_open (&hd, GCRY_MD_MD4, 0);
490   if (err != GPG_ERR_NO_ERROR)
491     return GC_INVALID_HASH;
492
493   gcry_md_write (hd, in, inlen);
494
495   p = gcry_md_read (hd, GCRY_MD_MD4);
496   if (p == NULL)
497     {
498       gcry_md_close (hd);
499       return GC_INVALID_HASH;
500     }
501
502   memcpy (resbuf, p, outlen);
503
504   gcry_md_close (hd);
505
506   return GC_OK;
507 }
508 #endif
509
510 #ifdef GC_USE_MD5
511 Gc_rc
512 gc_md5 (const void *in, size_t inlen, void *resbuf)
513 {
514   size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_MD5);
515   gcry_md_hd_t hd;
516   gpg_error_t err;
517   unsigned char *p;
518
519   assert (outlen == GC_MD5_DIGEST_SIZE);
520
521   err = gcry_md_open (&hd, GCRY_MD_MD5, 0);
522   if (err != GPG_ERR_NO_ERROR)
523     return GC_INVALID_HASH;
524
525   gcry_md_write (hd, in, inlen);
526
527   p = gcry_md_read (hd, GCRY_MD_MD5);
528   if (p == NULL)
529     {
530       gcry_md_close (hd);
531       return GC_INVALID_HASH;
532     }
533
534   memcpy (resbuf, p, outlen);
535
536   gcry_md_close (hd);
537
538   return GC_OK;
539 }
540 #endif
541
542 #ifdef GC_USE_SHA1
543 Gc_rc
544 gc_sha1 (const void *in, size_t inlen, void *resbuf)
545 {
546   size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
547   gcry_md_hd_t hd;
548   gpg_error_t err;
549   unsigned char *p;
550
551   assert (outlen == GC_SHA1_DIGEST_SIZE);
552
553   err = gcry_md_open (&hd, GCRY_MD_SHA1, 0);
554   if (err != GPG_ERR_NO_ERROR)
555     return GC_INVALID_HASH;
556
557   gcry_md_write (hd, in, inlen);
558
559   p = gcry_md_read (hd, GCRY_MD_SHA1);
560   if (p == NULL)
561     {
562       gcry_md_close (hd);
563       return GC_INVALID_HASH;
564     }
565
566   memcpy (resbuf, p, outlen);
567
568   gcry_md_close (hd);
569
570   return GC_OK;
571 }
572 #endif
573
574 #ifdef GC_USE_HMAC_MD5
575 Gc_rc
576 gc_hmac_md5 (const void *key, size_t keylen,
577              const void *in, size_t inlen, char *resbuf)
578 {
579   size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_MD5);
580   gcry_md_hd_t mdh;
581   unsigned char *hash;
582   gpg_error_t err;
583
584   assert (hlen == 16);
585
586   err = gcry_md_open (&mdh, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC);
587   if (err != GPG_ERR_NO_ERROR)
588     return GC_INVALID_HASH;
589
590   err = gcry_md_setkey (mdh, key, keylen);
591   if (err != GPG_ERR_NO_ERROR)
592     {
593       gcry_md_close (mdh);
594       return GC_INVALID_HASH;
595     }
596
597   gcry_md_write (mdh, in, inlen);
598
599   hash = gcry_md_read (mdh, GCRY_MD_MD5);
600   if (hash == NULL)
601     {
602       gcry_md_close (mdh);
603       return GC_INVALID_HASH;
604     }
605
606   memcpy (resbuf, hash, hlen);
607
608   gcry_md_close (mdh);
609
610   return GC_OK;
611 }
612 #endif
613
614 #ifdef GC_USE_HMAC_SHA1
615 Gc_rc
616 gc_hmac_sha1 (const void *key, size_t keylen,
617               const void *in, size_t inlen, char *resbuf)
618 {
619   size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
620   gcry_md_hd_t mdh;
621   unsigned char *hash;
622   gpg_error_t err;
623
624   assert (hlen == GC_SHA1_DIGEST_SIZE);
625
626   err = gcry_md_open (&mdh, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
627   if (err != GPG_ERR_NO_ERROR)
628     return GC_INVALID_HASH;
629
630   err = gcry_md_setkey (mdh, key, keylen);
631   if (err != GPG_ERR_NO_ERROR)
632     {
633       gcry_md_close (mdh);
634       return GC_INVALID_HASH;
635     }
636
637   gcry_md_write (mdh, in, inlen);
638
639   hash = gcry_md_read (mdh, GCRY_MD_SHA1);
640   if (hash == NULL)
641     {
642       gcry_md_close (mdh);
643       return GC_INVALID_HASH;
644     }
645
646   memcpy (resbuf, hash, hlen);
647
648   gcry_md_close (mdh);
649
650   return GC_OK;
651 }
652 #endif