Add gc-hmac-sha1.
[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 /* Get libgcrypt API. */
31 #include <gcrypt.h>
32
33 #include <assert.h>
34
35 /* Initialization. */
36
37 int
38 gc_init (void)
39 {
40   gcry_error_t err;
41
42   err = gcry_control (GCRYCTL_ANY_INITIALIZATION_P);
43   if (err == GPG_ERR_NO_ERROR)
44     {
45       if (gcry_check_version (GCRYPT_VERSION) == NULL)
46         return GC_INIT_ERROR;
47
48       err = gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0);
49       if (err != GPG_ERR_NO_ERROR)
50         return GC_INIT_ERROR;
51     }
52
53   return GC_OK;
54 }
55
56 void
57 gc_done (void)
58 {
59   return;
60 }
61
62 /* Randomness. */
63
64 int
65 gc_nonce (char *data, size_t datalen)
66 {
67   gcry_create_nonce ((unsigned char *) data, datalen);
68   return GC_OK;
69 }
70
71 int
72 gc_pseudo_random (char *data, size_t datalen)
73 {
74   gcry_randomize ((unsigned char *) data, datalen, GCRY_STRONG_RANDOM);
75   return GC_OK;
76 }
77
78 int
79 gc_random (char *data, size_t datalen)
80 {
81   gcry_randomize ((unsigned char *) data, datalen, GCRY_VERY_STRONG_RANDOM);
82   return GC_OK;
83 }
84
85 /* Memory allocation. */
86
87 void
88 gc_set_allocators (gc_malloc_t func_malloc,
89                    gc_malloc_t secure_malloc,
90                    gc_secure_check_t secure_check,
91                    gc_realloc_t func_realloc, gc_free_t func_free)
92 {
93   gcry_set_allocation_handler (func_malloc, secure_malloc, secure_check,
94                                func_realloc, func_free);
95 }
96
97 /* Hashes. */
98
99 int
100 gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
101 {
102   int gcryalg;
103
104   switch (hash)
105     {
106 #ifdef GC_USE_MD5
107     case GC_MD5:
108       gcryalg = GCRY_MD_MD5;
109       break;
110 #endif
111
112 #ifdef GC_USE_SHA1
113     case GC_SHA1:
114       gcryalg = GCRY_MD_SHA1;
115       break;
116 #endif
117
118     default:
119       return GC_INVALID_HASH;
120     }
121
122   gcry_md_hash_buffer (gcryalg, resbuf, in, inlen);
123
124   return GC_OK;
125 }
126
127 /* One-call interface. */
128
129 #ifdef GC_USE_MD5
130 int
131 gc_md5 (const void *in, size_t inlen, void *resbuf)
132 {
133   size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_MD5);
134   gcry_md_hd_t hd;
135   gpg_error_t err;
136   unsigned char *p;
137
138   assert (outlen == GC_MD5_DIGEST_SIZE);
139
140   err = gcry_md_open (&hd, GCRY_MD_MD5, 0);
141   if (err != GPG_ERR_NO_ERROR)
142     return GC_INVALID_HASH;
143
144   gcry_md_write (hd, in, inlen);
145
146   p = gcry_md_read (hd, GCRY_MD_MD5);
147   if (p == NULL)
148     {
149       gcry_md_close (hd);
150       return GC_INVALID_HASH;
151     }
152
153   memcpy (resbuf, p, outlen);
154
155   gcry_md_close (hd);
156
157   return GC_OK;
158 }
159 #endif
160
161 #ifdef GC_USE_SHA1
162 int
163 gc_sha1 (const void *in, size_t inlen, void *resbuf)
164 {
165   size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
166   gcry_md_hd_t hd;
167   gpg_error_t err;
168   unsigned char *p;
169
170   assert (outlen == GC_SHA1_DIGEST_SIZE);
171
172   err = gcry_md_open (&hd, GCRY_MD_SHA1, 0);
173   if (err != GPG_ERR_NO_ERROR)
174     return GC_INVALID_HASH;
175
176   gcry_md_write (hd, in, inlen);
177
178   p = gcry_md_read (hd, GCRY_MD_SHA1);
179   if (p == NULL)
180     {
181       gcry_md_close (hd);
182       return GC_INVALID_HASH;
183     }
184
185   memcpy (resbuf, p, outlen);
186
187   gcry_md_close (hd);
188
189   return GC_OK;
190 }
191 #endif
192
193 #ifdef GC_USE_HMAC_MD5
194 int
195 gc_hmac_md5 (const void *key, size_t keylen,
196              const void *in, size_t inlen, char *resbuf)
197 {
198   size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_MD5);
199   gcry_md_hd_t mdh;
200   unsigned char *hash;
201   gpg_error_t err;
202
203   assert (hlen == 16);
204
205   err = gcry_md_open (&mdh, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC);
206   if (err != GPG_ERR_NO_ERROR)
207     return GC_INVALID_HASH;
208
209   err = gcry_md_setkey (mdh, key, keylen);
210   if (err != GPG_ERR_NO_ERROR)
211     {
212       gcry_md_close (mdh);
213       return GC_INVALID_HASH;
214     }
215
216   gcry_md_write (mdh, in, inlen);
217
218   hash = gcry_md_read (mdh, GCRY_MD_MD5);
219   if (hash == NULL)
220     {
221       gcry_md_close (mdh);
222       return GC_INVALID_HASH;
223     }
224
225   memcpy (resbuf, hash, hlen);
226
227   gcry_md_close (mdh);
228
229   return GC_OK;
230 }
231 #endif
232
233 #ifdef GC_USE_HMAC_SHA1
234 int
235 gc_hmac_sha1 (const void *key, size_t keylen,
236               const void *in, size_t inlen, char *resbuf)
237 {
238   size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
239   gcry_md_hd_t mdh;
240   unsigned char *hash;
241   gpg_error_t err;
242
243   assert (hlen == 16);
244
245   err = gcry_md_open (&mdh, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
246   if (err != GPG_ERR_NO_ERROR)
247     return GC_INVALID_HASH;
248
249   err = gcry_md_setkey (mdh, key, keylen);
250   if (err != GPG_ERR_NO_ERROR)
251     {
252       gcry_md_close (mdh);
253       return GC_INVALID_HASH;
254     }
255
256   gcry_md_write (mdh, in, inlen);
257
258   hash = gcry_md_read (mdh, GCRY_MD_SHA1);
259   if (hash == NULL)
260     {
261       gcry_md_close (mdh);
262       return GC_INVALID_HASH;
263     }
264
265   memcpy (resbuf, hash, hlen);
266
267   gcry_md_close (mdh);
268
269   return GC_OK;
270 }
271 #endif