10841e8d43ada764c9e4a64d27c10d3a45811bcb
[gnulib.git] / 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   if (!ctx)
247     return GC_MALLOC_ERROR;
248
249   ctx->alg = hash;
250   ctx->mode = mode;
251
252   switch (hash)
253     {
254     case GC_MD2:
255       gcryalg = GCRY_MD_NONE;
256       break;
257
258     case GC_MD4:
259       gcryalg = GCRY_MD_MD4;
260       break;
261
262     case GC_MD5:
263       gcryalg = GCRY_MD_MD5;
264       break;
265
266     case GC_SHA1:
267       gcryalg = GCRY_MD_SHA1;
268       break;
269
270     case GC_RMD160:
271       gcryalg = GCRY_MD_RMD160;
272       break;
273
274     default:
275       rc = GC_INVALID_HASH;
276     }
277
278   switch (mode)
279     {
280     case 0:
281       gcrymode = 0;
282       break;
283
284     case GC_HMAC:
285       gcrymode = GCRY_MD_FLAG_HMAC;
286       break;
287
288     default:
289       rc = GC_INVALID_HASH;
290     }
291
292   if (rc == GC_OK && gcryalg != GCRY_MD_NONE)
293     {
294       err = gcry_md_open (&ctx->gch, gcryalg, gcrymode);
295       if (gcry_err_code (err))
296         rc = GC_INVALID_HASH;
297     }
298
299   if (rc == GC_OK)
300     *outhandle = ctx;
301   else
302     free (ctx);
303
304   return rc;
305 }
306
307 Gc_rc
308 gc_hash_clone (gc_hash_handle handle, gc_hash_handle * outhandle)
309 {
310   _gc_hash_ctx *in = handle;
311   _gc_hash_ctx *out;
312   int err;
313
314   *outhandle = out = calloc (sizeof (*out), 1);
315   if (!out)
316     return GC_MALLOC_ERROR;
317
318   memcpy (out, in, sizeof (*out));
319
320   err = gcry_md_copy (&out->gch, in->gch);
321   if (err)
322     {
323       free (out);
324       return GC_INVALID_HASH;
325     }
326
327   return GC_OK;
328 }
329
330 size_t
331 gc_hash_digest_length (Gc_hash hash)
332 {
333   size_t len;
334
335   switch (hash)
336     {
337     case GC_MD2:
338       len = GC_MD2_DIGEST_SIZE;
339       break;
340
341     case GC_MD4:
342       len = GC_MD4_DIGEST_SIZE;
343       break;
344
345     case GC_MD5:
346       len = GC_MD5_DIGEST_SIZE;
347       break;
348
349     case GC_RMD160:
350       len = GC_RMD160_DIGEST_SIZE;
351       break;
352
353     case GC_SHA1:
354       len = GC_SHA1_DIGEST_SIZE;
355       break;
356
357     default:
358       return 0;
359     }
360
361   return len;
362 }
363
364 void
365 gc_hash_hmac_setkey (gc_hash_handle handle, size_t len, const char *key)
366 {
367   _gc_hash_ctx *ctx = handle;
368 #ifdef GC_USE_MD2
369   if (ctx->alg != GC_MD2)
370 #endif
371     gcry_md_setkey (ctx->gch, key, len);
372 }
373
374 void
375 gc_hash_write (gc_hash_handle handle, size_t len, const char *data)
376 {
377   _gc_hash_ctx *ctx = handle;
378
379 #ifdef GC_USE_MD2
380   if (ctx->alg == GC_MD2)
381     md2_process_bytes (data, len, &ctx->md2Context);
382   else
383 #endif
384     gcry_md_write (ctx->gch, data, len);
385 }
386
387 const char *
388 gc_hash_read (gc_hash_handle handle)
389 {
390   _gc_hash_ctx *ctx = handle;
391   const char *digest;
392
393 #ifdef GC_USE_MD2
394   if (ctx->alg == GC_MD2)
395     {
396       md2_finish_ctx (&ctx->md2Context, ctx->hash);
397       digest = ctx->hash;
398     }
399   else
400 #endif
401     {
402       gcry_md_final (ctx->gch);
403       digest = gcry_md_read (ctx->gch, 0);
404     }
405
406   return digest;
407 }
408
409 void
410 gc_hash_close (gc_hash_handle handle)
411 {
412   _gc_hash_ctx *ctx = handle;
413
414 #ifdef GC_USE_MD2
415   if (ctx->alg != GC_MD2)
416 #endif
417     gcry_md_close (ctx->gch);
418
419   free (ctx);
420 }
421
422 Gc_rc
423 gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
424 {
425   int gcryalg;
426
427   switch (hash)
428     {
429 #ifdef GC_USE_MD2
430     case GC_MD2:
431       md2_buffer (in, inlen, resbuf);
432       return GC_OK;
433       break;
434 #endif
435
436 #ifdef GC_USE_MD4
437     case GC_MD4:
438       gcryalg = GCRY_MD_MD4;
439       break;
440 #endif
441
442 #ifdef GC_USE_MD5
443     case GC_MD5:
444       gcryalg = GCRY_MD_MD5;
445       break;
446 #endif
447
448 #ifdef GC_USE_SHA1
449     case GC_SHA1:
450       gcryalg = GCRY_MD_SHA1;
451       break;
452 #endif
453
454 #ifdef GC_USE_RMD160
455     case GC_RMD160:
456       gcryalg = GCRY_MD_RMD160;
457       break;
458 #endif
459
460     default:
461       return GC_INVALID_HASH;
462     }
463
464   gcry_md_hash_buffer (gcryalg, resbuf, in, inlen);
465
466   return GC_OK;
467 }
468
469 /* One-call interface. */
470
471 #ifdef GC_USE_MD2
472 Gc_rc
473 gc_md2 (const void *in, size_t inlen, void *resbuf)
474 {
475   md2_buffer (in, inlen, resbuf);
476   return GC_OK;
477 }
478 #endif
479
480 #ifdef GC_USE_MD4
481 Gc_rc
482 gc_md4 (const void *in, size_t inlen, void *resbuf)
483 {
484   size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_MD4);
485   gcry_md_hd_t hd;
486   gpg_error_t err;
487   unsigned char *p;
488
489   assert (outlen == GC_MD4_DIGEST_SIZE);
490
491   err = gcry_md_open (&hd, GCRY_MD_MD4, 0);
492   if (err != GPG_ERR_NO_ERROR)
493     return GC_INVALID_HASH;
494
495   gcry_md_write (hd, in, inlen);
496
497   p = gcry_md_read (hd, GCRY_MD_MD4);
498   if (p == NULL)
499     {
500       gcry_md_close (hd);
501       return GC_INVALID_HASH;
502     }
503
504   memcpy (resbuf, p, outlen);
505
506   gcry_md_close (hd);
507
508   return GC_OK;
509 }
510 #endif
511
512 #ifdef GC_USE_MD5
513 Gc_rc
514 gc_md5 (const void *in, size_t inlen, void *resbuf)
515 {
516   size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_MD5);
517   gcry_md_hd_t hd;
518   gpg_error_t err;
519   unsigned char *p;
520
521   assert (outlen == GC_MD5_DIGEST_SIZE);
522
523   err = gcry_md_open (&hd, GCRY_MD_MD5, 0);
524   if (err != GPG_ERR_NO_ERROR)
525     return GC_INVALID_HASH;
526
527   gcry_md_write (hd, in, inlen);
528
529   p = gcry_md_read (hd, GCRY_MD_MD5);
530   if (p == NULL)
531     {
532       gcry_md_close (hd);
533       return GC_INVALID_HASH;
534     }
535
536   memcpy (resbuf, p, outlen);
537
538   gcry_md_close (hd);
539
540   return GC_OK;
541 }
542 #endif
543
544 #ifdef GC_USE_SHA1
545 Gc_rc
546 gc_sha1 (const void *in, size_t inlen, void *resbuf)
547 {
548   size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
549   gcry_md_hd_t hd;
550   gpg_error_t err;
551   unsigned char *p;
552
553   assert (outlen == GC_SHA1_DIGEST_SIZE);
554
555   err = gcry_md_open (&hd, GCRY_MD_SHA1, 0);
556   if (err != GPG_ERR_NO_ERROR)
557     return GC_INVALID_HASH;
558
559   gcry_md_write (hd, in, inlen);
560
561   p = gcry_md_read (hd, GCRY_MD_SHA1);
562   if (p == NULL)
563     {
564       gcry_md_close (hd);
565       return GC_INVALID_HASH;
566     }
567
568   memcpy (resbuf, p, outlen);
569
570   gcry_md_close (hd);
571
572   return GC_OK;
573 }
574 #endif
575
576 #ifdef GC_USE_HMAC_MD5
577 Gc_rc
578 gc_hmac_md5 (const void *key, size_t keylen,
579              const void *in, size_t inlen, char *resbuf)
580 {
581   size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_MD5);
582   gcry_md_hd_t mdh;
583   unsigned char *hash;
584   gpg_error_t err;
585
586   assert (hlen == 16);
587
588   err = gcry_md_open (&mdh, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC);
589   if (err != GPG_ERR_NO_ERROR)
590     return GC_INVALID_HASH;
591
592   err = gcry_md_setkey (mdh, key, keylen);
593   if (err != GPG_ERR_NO_ERROR)
594     {
595       gcry_md_close (mdh);
596       return GC_INVALID_HASH;
597     }
598
599   gcry_md_write (mdh, in, inlen);
600
601   hash = gcry_md_read (mdh, GCRY_MD_MD5);
602   if (hash == NULL)
603     {
604       gcry_md_close (mdh);
605       return GC_INVALID_HASH;
606     }
607
608   memcpy (resbuf, hash, hlen);
609
610   gcry_md_close (mdh);
611
612   return GC_OK;
613 }
614 #endif
615
616 #ifdef GC_USE_HMAC_SHA1
617 Gc_rc
618 gc_hmac_sha1 (const void *key, size_t keylen,
619               const void *in, size_t inlen, char *resbuf)
620 {
621   size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
622   gcry_md_hd_t mdh;
623   unsigned char *hash;
624   gpg_error_t err;
625
626   assert (hlen == GC_SHA1_DIGEST_SIZE);
627
628   err = gcry_md_open (&mdh, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
629   if (err != GPG_ERR_NO_ERROR)
630     return GC_INVALID_HASH;
631
632   err = gcry_md_setkey (mdh, key, keylen);
633   if (err != GPG_ERR_NO_ERROR)
634     {
635       gcry_md_close (mdh);
636       return GC_INVALID_HASH;
637     }
638
639   gcry_md_write (mdh, in, inlen);
640
641   hash = gcry_md_read (mdh, GCRY_MD_SHA1);
642   if (hash == NULL)
643     {
644       gcry_md_close (mdh);
645       return GC_INVALID_HASH;
646     }
647
648   memcpy (resbuf, hash, hlen);
649
650   gcry_md_close (mdh);
651
652   return GC_OK;
653 }
654 #endif