author | zautrix <zautrix> | 2004-10-19 20:16:14 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-10-19 20:16:14 (UTC) |
commit | eca49bb06a71980ef61d078904573f25890fc7f2 (patch) (unidiff) | |
tree | c5338e3b12430248979a9ac2c1c7e6646ea9ecdf /pwmanager/libcrypt/cipher/md.c | |
parent | 53cc32b6e7b1f672bf91b2baf2df6c1e8baf3e0a (diff) | |
download | kdepimpi-eca49bb06a71980ef61d078904573f25890fc7f2.zip kdepimpi-eca49bb06a71980ef61d078904573f25890fc7f2.tar.gz kdepimpi-eca49bb06a71980ef61d078904573f25890fc7f2.tar.bz2 |
Initial revision
Diffstat (limited to 'pwmanager/libcrypt/cipher/md.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | pwmanager/libcrypt/cipher/md.c | 1253 |
1 files changed, 1253 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/cipher/md.c b/pwmanager/libcrypt/cipher/md.c new file mode 100644 index 0000000..06b46e6 --- a/dev/null +++ b/pwmanager/libcrypt/cipher/md.c | |||
@@ -0,0 +1,1253 @@ | |||
1 | /* md.c - message digest dispatcher | ||
2 | * Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of Libgcrypt. | ||
5 | * | ||
6 | * Libgcrypt is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Lesser general Public License as | ||
8 | * published by the Free Software Foundation; either version 2.1 of | ||
9 | * the License, or (at your option) any later version. | ||
10 | * | ||
11 | * Libgcrypt is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | */ | ||
20 | |||
21 | #include <config.h> | ||
22 | #include <stdio.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | #include <errno.h> | ||
26 | #include <assert.h> | ||
27 | |||
28 | #include "g10lib.h" | ||
29 | #include "cipher.h" | ||
30 | #include "ath.h" | ||
31 | |||
32 | #include "rmd.h" | ||
33 | |||
34 | static struct digest_table_entry | ||
35 | { | ||
36 | gcry_md_spec_t *digest; | ||
37 | unsigned int algorithm; | ||
38 | } digest_table[] = | ||
39 | { | ||
40 | #if USE_CRC | ||
41 | { &_gcry_digest_spec_crc32, GCRY_MD_CRC32 }, | ||
42 | { &_gcry_digest_spec_crc32_rfc1510, GCRY_MD_CRC32_RFC1510 }, | ||
43 | { &_gcry_digest_spec_crc24_rfc2440, GCRY_MD_CRC24_RFC2440 }, | ||
44 | #endif | ||
45 | #if USE_MD4 | ||
46 | { &_gcry_digest_spec_md4, GCRY_MD_MD4 }, | ||
47 | #endif | ||
48 | #if USE_MD5 | ||
49 | { &_gcry_digest_spec_md5, GCRY_MD_MD5 }, | ||
50 | #endif | ||
51 | #if USE_RMD160 | ||
52 | { &_gcry_digest_spec_rmd160, GCRY_MD_RMD160 }, | ||
53 | #endif | ||
54 | #if USE_SHA1 | ||
55 | { &_gcry_digest_spec_sha1, GCRY_MD_SHA1 }, | ||
56 | #endif | ||
57 | #if USE_SHA256 | ||
58 | { &_gcry_digest_spec_sha256, GCRY_MD_SHA256 }, | ||
59 | #endif | ||
60 | #if USE_SHA512 | ||
61 | { &_gcry_digest_spec_sha512, GCRY_MD_SHA512 }, | ||
62 | { &_gcry_digest_spec_sha384, GCRY_MD_SHA384 }, | ||
63 | #endif | ||
64 | #if USE_TIGER | ||
65 | { &_gcry_digest_spec_tiger, GCRY_MD_TIGER }, | ||
66 | #endif | ||
67 | { NULL }, | ||
68 | }; | ||
69 | |||
70 | /* List of registered digests. */ | ||
71 | static gcry_module_t digests_registered; | ||
72 | |||
73 | /* This is the lock protecting DIGESTS_REGISTERED. */ | ||
74 | static ath_mutex_t digests_registered_lock = ATH_MUTEX_INITIALIZER; | ||
75 | |||
76 | /* Flag to check wether the default ciphers have already been | ||
77 | registered. */ | ||
78 | static int default_digests_registered; | ||
79 | |||
80 | typedef struct gcry_md_list | ||
81 | { | ||
82 | gcry_md_spec_t *digest; | ||
83 | gcry_module_t module; | ||
84 | struct gcry_md_list *next; | ||
85 | size_t actual_struct_size; /* Allocated size of this structure. */ | ||
86 | PROPERLY_ALIGNED_TYPE context; | ||
87 | } GcryDigestEntry; | ||
88 | |||
89 | /* this structure is put right after the gcry_md_hd_t buffer, so that | ||
90 | * only one memory block is needed. */ | ||
91 | struct gcry_md_context | ||
92 | { | ||
93 | int magic; | ||
94 | size_t actual_handle_size; /* Allocated size of this handle. */ | ||
95 | int secure; | ||
96 | FILE *debug; | ||
97 | int finalized; | ||
98 | GcryDigestEntry *list; | ||
99 | byte *macpads; | ||
100 | }; | ||
101 | |||
102 | |||
103 | #define CTX_MAGIC_NORMAL 0x11071961 | ||
104 | #define CTX_MAGIC_SECURE 0x16917011 | ||
105 | |||
106 | /* Convenient macro for registering the default digests. */ | ||
107 | #define REGISTER_DEFAULT_DIGESTS \ | ||
108 | do \ | ||
109 | { \ | ||
110 | ath_mutex_lock (&digests_registered_lock); \ | ||
111 | if (! default_digests_registered) \ | ||
112 | { \ | ||
113 | gcry_md_register_default (); \ | ||
114 | default_digests_registered = 1; \ | ||
115 | } \ | ||
116 | ath_mutex_unlock (&digests_registered_lock); \ | ||
117 | } \ | ||
118 | while (0) | ||
119 | |||
120 | |||
121 | static const char * digest_algo_to_string( int algo ); | ||
122 | static gcry_err_code_t check_digest_algo (int algo); | ||
123 | static gcry_err_code_t md_open (gcry_md_hd_t *h, int algo, | ||
124 | int secure, int hmac); | ||
125 | static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo); | ||
126 | static gcry_err_code_t md_copy (gcry_md_hd_t a, gcry_md_hd_t *b); | ||
127 | static void md_close (gcry_md_hd_t a); | ||
128 | static void md_write (gcry_md_hd_t a, byte *inbuf, size_t inlen); | ||
129 | static void md_final(gcry_md_hd_t a); | ||
130 | static byte *md_read( gcry_md_hd_t a, int algo ); | ||
131 | static int md_get_algo( gcry_md_hd_t a ); | ||
132 | static int md_digest_length( int algo ); | ||
133 | static const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ); | ||
134 | static void md_start_debug( gcry_md_hd_t a, char *suffix ); | ||
135 | static void md_stop_debug( gcry_md_hd_t a ); | ||
136 | |||
137 | |||
138 | |||
139 | |||
140 | /* Internal function. Register all the ciphers included in | ||
141 | CIPHER_TABLE. Returns zero on success or an error code. */ | ||
142 | static void | ||
143 | gcry_md_register_default (void) | ||
144 | { | ||
145 | gcry_err_code_t err = 0; | ||
146 | int i; | ||
147 | |||
148 | for (i = 0; (! err) && digest_table[i].digest; i++) | ||
149 | err = _gcry_module_add (&digests_registered, | ||
150 | digest_table[i].algorithm, | ||
151 | (void *) digest_table[i].digest, | ||
152 | NULL); | ||
153 | |||
154 | if (err) | ||
155 | BUG (); | ||
156 | } | ||
157 | |||
158 | /* Internal callback function. */ | ||
159 | static int | ||
160 | gcry_md_lookup_func_name (void *spec, void *data) | ||
161 | { | ||
162 | gcry_md_spec_t *digest = (gcry_md_spec_t *) spec; | ||
163 | char *name = (char *) data; | ||
164 | |||
165 | return (! stricmp (digest->name, name)); | ||
166 | } | ||
167 | |||
168 | /* Internal callback function. Used via _gcry_module_lookup. */ | ||
169 | static int | ||
170 | gcry_md_lookup_func_oid (void *spec, void *data) | ||
171 | { | ||
172 | gcry_md_spec_t *digest = (gcry_md_spec_t *) spec; | ||
173 | char *oid = (char *) data; | ||
174 | gcry_md_oid_spec_t *oid_specs = digest->oids; | ||
175 | int ret = 0, i; | ||
176 | |||
177 | if (oid_specs) | ||
178 | { | ||
179 | for (i = 0; oid_specs[i].oidstring && (! ret); i++) | ||
180 | if (! stricmp (oid, oid_specs[i].oidstring)) | ||
181 | ret = 1; | ||
182 | } | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | /* Internal function. Lookup a digest entry by it's name. */ | ||
188 | static gcry_module_t | ||
189 | gcry_md_lookup_name (const char *name) | ||
190 | { | ||
191 | gcry_module_t digest; | ||
192 | |||
193 | digest = _gcry_module_lookup (digests_registered, (void *) name, | ||
194 | gcry_md_lookup_func_name); | ||
195 | |||
196 | return digest; | ||
197 | } | ||
198 | |||
199 | /* Internal function. Lookup a cipher entry by it's oid. */ | ||
200 | static gcry_module_t | ||
201 | gcry_md_lookup_oid (const char *oid) | ||
202 | { | ||
203 | gcry_module_t digest; | ||
204 | |||
205 | digest = _gcry_module_lookup (digests_registered, (void *) oid, | ||
206 | gcry_md_lookup_func_oid); | ||
207 | |||
208 | return digest; | ||
209 | } | ||
210 | |||
211 | /* Register a new digest module whose specification can be found in | ||
212 | DIGEST. On success, a new algorithm ID is stored in ALGORITHM_ID | ||
213 | and a pointer representhing this module is stored in MODULE. */ | ||
214 | gcry_error_t | ||
215 | gcry_md_register (gcry_md_spec_t *digest, | ||
216 | unsigned int *algorithm_id, | ||
217 | gcry_module_t *module) | ||
218 | { | ||
219 | gcry_err_code_t err = 0; | ||
220 | gcry_module_t mod; | ||
221 | |||
222 | ath_mutex_lock (&digests_registered_lock); | ||
223 | err = _gcry_module_add (&digests_registered, 0, | ||
224 | (void *) digest, &mod); | ||
225 | ath_mutex_unlock (&digests_registered_lock); | ||
226 | |||
227 | if (! err) | ||
228 | { | ||
229 | *module = mod; | ||
230 | *algorithm_id = mod->mod_id; | ||
231 | } | ||
232 | |||
233 | return gcry_error (err); | ||
234 | } | ||
235 | |||
236 | /* Unregister the digest identified by ID, which must have been | ||
237 | registered with gcry_digest_register. */ | ||
238 | void | ||
239 | gcry_md_unregister (gcry_module_t module) | ||
240 | { | ||
241 | ath_mutex_lock (&digests_registered_lock); | ||
242 | _gcry_module_release (module); | ||
243 | ath_mutex_unlock (&digests_registered_lock); | ||
244 | } | ||
245 | |||
246 | |||
247 | static int | ||
248 | search_oid (const char *oid, int *algorithm, gcry_md_oid_spec_t *oid_spec) | ||
249 | { | ||
250 | gcry_module_t module; | ||
251 | int ret = 0; | ||
252 | |||
253 | if (oid && ((! strncmp (oid, "oid.", 4)) | ||
254 | || (! strncmp (oid, "OID.", 4)))) | ||
255 | oid += 4; | ||
256 | |||
257 | module = gcry_md_lookup_oid (oid); | ||
258 | if (module) | ||
259 | { | ||
260 | gcry_md_spec_t *digest = module->spec; | ||
261 | int i; | ||
262 | |||
263 | for (i = 0; digest->oids[i].oidstring && !ret; i++) | ||
264 | if (! stricmp (oid, digest->oids[i].oidstring)) | ||
265 | { | ||
266 | if (algorithm) | ||
267 | *algorithm = module->mod_id; | ||
268 | if (oid_spec) | ||
269 | *oid_spec = digest->oids[i]; | ||
270 | ret = 1; | ||
271 | } | ||
272 | _gcry_module_release (module); | ||
273 | } | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | /**************** | ||
279 | * Map a string to the digest algo | ||
280 | */ | ||
281 | int | ||
282 | gcry_md_map_name (const char *string) | ||
283 | { | ||
284 | gcry_module_t digest; | ||
285 | int ret, algorithm = 0; | ||
286 | |||
287 | if (! string) | ||
288 | return 0; | ||
289 | |||
290 | REGISTER_DEFAULT_DIGESTS; | ||
291 | |||
292 | /* If the string starts with a digit (optionally prefixed with | ||
293 | either "OID." or "oid."), we first look into our table of ASN.1 | ||
294 | object identifiers to figure out the algorithm */ | ||
295 | |||
296 | ath_mutex_lock (&digests_registered_lock); | ||
297 | |||
298 | ret = search_oid (string, &algorithm, NULL); | ||
299 | if (! ret) | ||
300 | { | ||
301 | /* Not found, search for an acording diget name. */ | ||
302 | digest = gcry_md_lookup_name (string); | ||
303 | if (digest) | ||
304 | { | ||
305 | algorithm = digest->mod_id; | ||
306 | _gcry_module_release (digest); | ||
307 | } | ||
308 | } | ||
309 | ath_mutex_unlock (&digests_registered_lock); | ||
310 | |||
311 | return algorithm; | ||
312 | } | ||
313 | |||
314 | |||
315 | /**************** | ||
316 | * Map a digest algo to a string | ||
317 | */ | ||
318 | static const char * | ||
319 | digest_algo_to_string (int algorithm) | ||
320 | { | ||
321 | const char *name = NULL; | ||
322 | gcry_module_t digest; | ||
323 | |||
324 | REGISTER_DEFAULT_DIGESTS; | ||
325 | |||
326 | ath_mutex_lock (&digests_registered_lock); | ||
327 | digest = _gcry_module_lookup_id (digests_registered, algorithm); | ||
328 | if (digest) | ||
329 | { | ||
330 | name = ((gcry_md_spec_t *) digest->spec)->name; | ||
331 | _gcry_module_release (digest); | ||
332 | } | ||
333 | ath_mutex_unlock (&digests_registered_lock); | ||
334 | |||
335 | return name; | ||
336 | } | ||
337 | |||
338 | /**************** | ||
339 | * This function simply returns the name of the algorithm or some constant | ||
340 | * string when there is no algo. It will never return NULL. | ||
341 | * Usethe macro gcry_md_test_algo() to check whether the algorithm | ||
342 | * is valid. | ||
343 | */ | ||
344 | const char * | ||
345 | gcry_md_algo_name (int algorithm) | ||
346 | { | ||
347 | const char *s = digest_algo_to_string (algorithm); | ||
348 | return s ? s : "?"; | ||
349 | } | ||
350 | |||
351 | |||
352 | static gcry_err_code_t | ||
353 | check_digest_algo (int algorithm) | ||
354 | { | ||
355 | gcry_err_code_t rc = 0; | ||
356 | gcry_module_t digest; | ||
357 | |||
358 | REGISTER_DEFAULT_DIGESTS; | ||
359 | |||
360 | ath_mutex_lock (&digests_registered_lock); | ||
361 | digest = _gcry_module_lookup_id (digests_registered, algorithm); | ||
362 | if (digest) | ||
363 | _gcry_module_release (digest); | ||
364 | else | ||
365 | rc = GPG_ERR_DIGEST_ALGO; | ||
366 | ath_mutex_unlock (&digests_registered_lock); | ||
367 | |||
368 | return rc; | ||
369 | } | ||
370 | |||
371 | |||
372 | |||
373 | /**************** | ||
374 | * Open a message digest handle for use with algorithm ALGO. | ||
375 | * More algorithms may be added by md_enable(). The initial algorithm | ||
376 | * may be 0. | ||
377 | */ | ||
378 | static gcry_err_code_t | ||
379 | md_open (gcry_md_hd_t *h, int algo, int secure, int hmac) | ||
380 | { | ||
381 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
382 | int bufsize = secure ? 512 : 1024; | ||
383 | struct gcry_md_context *ctx; | ||
384 | gcry_md_hd_t hd; | ||
385 | size_t n; | ||
386 | |||
387 | /* Allocate a memory area to hold the caller visible buffer with it's | ||
388 | * control information and the data required by this module. Set the | ||
389 | * context pointer at the beginning to this area. | ||
390 | * We have to use this strange scheme because we want to hide the | ||
391 | * internal data but have a variable sized buffer. | ||
392 | * | ||
393 | *+---+------+---........------+-------------+ | ||
394 | * !ctx! bctl ! buffer ! private ! | ||
395 | *+---+------+---........------+-------------+ | ||
396 | * ! ^ | ||
397 | * !---------------------------! | ||
398 | * | ||
399 | * We have to make sure that private is well aligned. | ||
400 | */ | ||
401 | n = sizeof (struct gcry_md_handle) + bufsize; | ||
402 | n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1) | ||
403 | / sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE); | ||
404 | |||
405 | /* Allocate and set the Context pointer to the private data */ | ||
406 | if (secure) | ||
407 | hd = gcry_malloc_secure (n + sizeof (struct gcry_md_context)); | ||
408 | else | ||
409 | hd = gcry_malloc (n + sizeof (struct gcry_md_context)); | ||
410 | |||
411 | if (! hd) | ||
412 | err = gpg_err_code_from_errno (errno); | ||
413 | |||
414 | if (! err) | ||
415 | { | ||
416 | hd->ctx = ctx = (struct gcry_md_context *) ((char *) hd + n); | ||
417 | /* Setup the globally visible data (bctl in the diagram).*/ | ||
418 | hd->bufsize = n - sizeof (struct gcry_md_handle) + 1; | ||
419 | hd->bufpos = 0; | ||
420 | |||
421 | /* Initialize the private data. */ | ||
422 | memset (hd->ctx, 0, sizeof *hd->ctx); | ||
423 | ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; | ||
424 | ctx->actual_handle_size = n + sizeof (struct gcry_md_context); | ||
425 | ctx->secure = secure; | ||
426 | |||
427 | if (hmac) | ||
428 | { | ||
429 | ctx->macpads = gcry_malloc_secure (128); | ||
430 | if (! ctx->macpads) | ||
431 | { | ||
432 | md_close (hd); | ||
433 | err = gpg_err_code_from_errno (errno); | ||
434 | } | ||
435 | } | ||
436 | } | ||
437 | |||
438 | if (! err) | ||
439 | { | ||
440 | /* FIXME: should we really do that? - yes [-wk] */ | ||
441 | _gcry_fast_random_poll (); | ||
442 | |||
443 | if (algo) | ||
444 | { | ||
445 | err = md_enable (hd, algo); | ||
446 | if (err) | ||
447 | md_close (hd); | ||
448 | } | ||
449 | } | ||
450 | |||
451 | if (! err) | ||
452 | *h = hd; | ||
453 | |||
454 | return err; | ||
455 | } | ||
456 | |||
457 | /* Create a message digest object for algorithm ALGO. FLAGS may be | ||
458 | given as an bitwise OR of the gcry_md_flags values. ALGO may be | ||
459 | given as 0 if the algorithms to be used are later set using | ||
460 | gcry_md_enable. H is guaranteed to be a valid handle or NULL on | ||
461 | error. */ | ||
462 | gcry_error_t | ||
463 | gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags) | ||
464 | { | ||
465 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
466 | gcry_md_hd_t hd; | ||
467 | |||
468 | if ((flags & ~(GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC))) | ||
469 | err = GPG_ERR_INV_ARG; | ||
470 | else | ||
471 | { | ||
472 | err = md_open (&hd, algo, (flags & GCRY_MD_FLAG_SECURE), | ||
473 | (flags & GCRY_MD_FLAG_HMAC)); | ||
474 | } | ||
475 | |||
476 | *h = err? NULL : hd; | ||
477 | return gcry_error (err); | ||
478 | } | ||
479 | |||
480 | |||
481 | |||
482 | static gcry_err_code_t | ||
483 | md_enable (gcry_md_hd_t hd, int algorithm) | ||
484 | { | ||
485 | struct gcry_md_context *h = hd->ctx; | ||
486 | gcry_md_spec_t *digest = NULL; | ||
487 | GcryDigestEntry *entry; | ||
488 | gcry_module_t module; | ||
489 | gcry_err_code_t err = 0; | ||
490 | |||
491 | for (entry = h->list; entry; entry = entry->next) | ||
492 | if (entry->module->mod_id == algorithm) | ||
493 | return err; /* already enabled */ | ||
494 | |||
495 | REGISTER_DEFAULT_DIGESTS; | ||
496 | |||
497 | ath_mutex_lock (&digests_registered_lock); | ||
498 | module = _gcry_module_lookup_id (digests_registered, algorithm); | ||
499 | ath_mutex_unlock (&digests_registered_lock); | ||
500 | if (! module) | ||
501 | { | ||
502 | log_debug ("md_enable: algorithm %d not available\n", algorithm); | ||
503 | err = GPG_ERR_DIGEST_ALGO; | ||
504 | } | ||
505 | else | ||
506 | digest = (gcry_md_spec_t *) module->spec; | ||
507 | |||
508 | if (! err) | ||
509 | { | ||
510 | size_t size = (sizeof (*entry) | ||
511 | + digest->contextsize | ||
512 | - sizeof (entry->context)); | ||
513 | |||
514 | /* And allocate a new list entry. */ | ||
515 | if (h->secure) | ||
516 | entry = gcry_malloc_secure (size); | ||
517 | else | ||
518 | entry = gcry_malloc (size); | ||
519 | |||
520 | if (! entry) | ||
521 | err = gpg_err_code_from_errno (errno); | ||
522 | else | ||
523 | { | ||
524 | entry->digest = digest; | ||
525 | entry->module = module; | ||
526 | entry->next = h->list; | ||
527 | entry->actual_struct_size = size; | ||
528 | h->list = entry; | ||
529 | |||
530 | /* And init this instance. */ | ||
531 | entry->digest->init (&entry->context.c); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | if (err) | ||
536 | { | ||
537 | if (module) | ||
538 | { | ||
539 | ath_mutex_lock (&digests_registered_lock); | ||
540 | _gcry_module_release (module); | ||
541 | ath_mutex_unlock (&digests_registered_lock); | ||
542 | } | ||
543 | } | ||
544 | |||
545 | return err; | ||
546 | } | ||
547 | |||
548 | |||
549 | gcry_error_t | ||
550 | gcry_md_enable (gcry_md_hd_t hd, int algorithm) | ||
551 | { | ||
552 | gcry_err_code_t err = md_enable (hd, algorithm); | ||
553 | return gcry_error (err); | ||
554 | } | ||
555 | |||
556 | static gcry_err_code_t | ||
557 | md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd) | ||
558 | { | ||
559 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
560 | struct gcry_md_context *a = ahd->ctx; | ||
561 | struct gcry_md_context *b; | ||
562 | GcryDigestEntry *ar, *br; | ||
563 | gcry_md_hd_t bhd; | ||
564 | size_t n; | ||
565 | |||
566 | if (ahd->bufpos) | ||
567 | md_write (ahd, NULL, 0); | ||
568 | |||
569 | n = (char *) ahd->ctx - (char *) ahd; | ||
570 | if (a->secure) | ||
571 | bhd = gcry_malloc_secure (n + sizeof (struct gcry_md_context)); | ||
572 | else | ||
573 | bhd = gcry_malloc (n + sizeof (struct gcry_md_context)); | ||
574 | |||
575 | if (! bhd) | ||
576 | err = gpg_err_code_from_errno (errno); | ||
577 | |||
578 | if (! err) | ||
579 | { | ||
580 | bhd->ctx = b = (struct gcry_md_context *) ((char *) bhd + n); | ||
581 | /* No need to copy the buffer due to the write above. */ | ||
582 | assert (ahd->bufsize == (n - sizeof (struct gcry_md_handle) + 1)); | ||
583 | bhd->bufsize = ahd->bufsize; | ||
584 | bhd->bufpos = 0; | ||
585 | assert (! ahd->bufpos); | ||
586 | memcpy (b, a, sizeof *a); | ||
587 | b->list = NULL; | ||
588 | b->debug = NULL; | ||
589 | if (a->macpads) | ||
590 | { | ||
591 | b->macpads = gcry_malloc_secure (128); | ||
592 | if (! b->macpads) | ||
593 | { | ||
594 | md_close (bhd); | ||
595 | err = gpg_err_code_from_errno (errno); | ||
596 | } | ||
597 | else | ||
598 | memcpy (b->macpads, a->macpads, 128); | ||
599 | } | ||
600 | } | ||
601 | |||
602 | /* Copy the complete list of algorithms. The copied list is | ||
603 | reversed, but that doesn't matter. */ | ||
604 | if (! err) | ||
605 | for (ar = a->list; ar; ar = ar->next) | ||
606 | { | ||
607 | if (a->secure) | ||
608 | br = gcry_xmalloc_secure (sizeof *br | ||
609 | + ar->digest->contextsize | ||
610 | - sizeof(ar->context)); | ||
611 | else | ||
612 | br = gcry_xmalloc (sizeof *br | ||
613 | + ar->digest->contextsize | ||
614 | - sizeof (ar->context)); | ||
615 | memcpy (br, ar, | ||
616 | sizeof (*br) + ar->digest->contextsize - sizeof (ar->context)); | ||
617 | br->next = b->list; | ||
618 | b->list = br; | ||
619 | |||
620 | /* Add a reference to the module. */ | ||
621 | ath_mutex_lock (&digests_registered_lock); | ||
622 | _gcry_module_use (br->module); | ||
623 | ath_mutex_unlock (&digests_registered_lock); | ||
624 | } | ||
625 | |||
626 | if (a->debug) | ||
627 | md_start_debug (bhd, "unknown"); | ||
628 | |||
629 | if (! err) | ||
630 | *b_hd = bhd; | ||
631 | |||
632 | return err; | ||
633 | } | ||
634 | |||
635 | gcry_error_t | ||
636 | gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd) | ||
637 | { | ||
638 | gcry_err_code_t err = md_copy (hd, handle); | ||
639 | if (err) | ||
640 | *handle = NULL; | ||
641 | return gcry_error (err); | ||
642 | } | ||
643 | |||
644 | /* | ||
645 | * Reset all contexts and discard any buffered stuff. This may be used | ||
646 | * instead of a md_close(); md_open(). | ||
647 | */ | ||
648 | void | ||
649 | gcry_md_reset (gcry_md_hd_t a) | ||
650 | { | ||
651 | GcryDigestEntry *r; | ||
652 | |||
653 | a->bufpos = a->ctx->finalized = 0; | ||
654 | |||
655 | for (r = a->ctx->list; r; r = r->next) | ||
656 | { | ||
657 | memset (r->context.c, 0, r->digest->contextsize); | ||
658 | (*r->digest->init) (&r->context.c); | ||
659 | } | ||
660 | if (a->ctx->macpads) | ||
661 | md_write (a, a->ctx->macpads, 64); /* inner pad */ | ||
662 | } | ||
663 | |||
664 | static void | ||
665 | md_close (gcry_md_hd_t a) | ||
666 | { | ||
667 | GcryDigestEntry *r, *r2; | ||
668 | |||
669 | if (! a) | ||
670 | return; | ||
671 | if (a->ctx->debug) | ||
672 | md_stop_debug (a); | ||
673 | for (r = a->ctx->list; r; r = r2) | ||
674 | { | ||
675 | r2 = r->next; | ||
676 | ath_mutex_lock (&digests_registered_lock); | ||
677 | _gcry_module_release (r->module); | ||
678 | ath_mutex_unlock (&digests_registered_lock); | ||
679 | wipememory (r, r->actual_struct_size); | ||
680 | gcry_free (r); | ||
681 | } | ||
682 | |||
683 | if (a->ctx->macpads) | ||
684 | { | ||
685 | wipememory (a->ctx->macpads, 128); | ||
686 | gcry_free(a->ctx->macpads); | ||
687 | } | ||
688 | |||
689 | wipememory (a, a->ctx->actual_handle_size); | ||
690 | gcry_free(a); | ||
691 | } | ||
692 | |||
693 | void | ||
694 | gcry_md_close (gcry_md_hd_t hd) | ||
695 | { | ||
696 | md_close (hd); | ||
697 | } | ||
698 | |||
699 | static void | ||
700 | md_write (gcry_md_hd_t a, byte *inbuf, size_t inlen) | ||
701 | { | ||
702 | GcryDigestEntry *r; | ||
703 | |||
704 | if (a->ctx->debug) | ||
705 | { | ||
706 | if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1) | ||
707 | BUG(); | ||
708 | if (inlen && fwrite (inbuf, inlen, 1, a->ctx->debug) != 1) | ||
709 | BUG(); | ||
710 | } | ||
711 | |||
712 | for (r = a->ctx->list; r; r = r->next) | ||
713 | { | ||
714 | if (a->bufpos) | ||
715 | (*r->digest->write) (&r->context.c, a->buf, a->bufpos); | ||
716 | (*r->digest->write) (&r->context.c, inbuf, inlen); | ||
717 | } | ||
718 | a->bufpos = 0; | ||
719 | } | ||
720 | |||
721 | void | ||
722 | gcry_md_write (gcry_md_hd_t hd, const void *inbuf, size_t inlen) | ||
723 | { | ||
724 | md_write (hd, (unsigned char *) inbuf, inlen); | ||
725 | } | ||
726 | |||
727 | static void | ||
728 | md_final (gcry_md_hd_t a) | ||
729 | { | ||
730 | GcryDigestEntry *r; | ||
731 | |||
732 | if (a->ctx->finalized) | ||
733 | return; | ||
734 | |||
735 | if (a->bufpos) | ||
736 | md_write (a, NULL, 0); | ||
737 | |||
738 | for (r = a->ctx->list; r; r = r->next) | ||
739 | (*r->digest->final) (&r->context.c); | ||
740 | |||
741 | a->ctx->finalized = 1; | ||
742 | |||
743 | if (a->ctx->macpads) | ||
744 | { | ||
745 | /* Finish the hmac. */ | ||
746 | int algo = md_get_algo (a); | ||
747 | byte *p = md_read (a, algo); | ||
748 | size_t dlen = md_digest_length (algo); | ||
749 | gcry_md_hd_t om; | ||
750 | gcry_err_code_t err = md_open (&om, algo, a->ctx->secure, 0); | ||
751 | |||
752 | if (err) | ||
753 | _gcry_fatal_error (err, NULL); | ||
754 | md_write (om, a->ctx->macpads+64, 64); | ||
755 | md_write (om, p, dlen); | ||
756 | md_final (om); | ||
757 | /* Replace our digest with the mac (they have the same size). */ | ||
758 | memcpy (p, md_read (om, algo), dlen); | ||
759 | md_close (om); | ||
760 | } | ||
761 | } | ||
762 | |||
763 | static gcry_err_code_t | ||
764 | prepare_macpads( gcry_md_hd_t hd, const byte *key, size_t keylen) | ||
765 | { | ||
766 | int i; | ||
767 | int algo = md_get_algo( hd ); | ||
768 | byte *helpkey = NULL; | ||
769 | byte *ipad, *opad; | ||
770 | |||
771 | if ( !algo ) | ||
772 | return GPG_ERR_DIGEST_ALGO; /* i.e. no algo enabled */ | ||
773 | |||
774 | if ( keylen > 64 ) | ||
775 | { | ||
776 | helpkey = gcry_malloc_secure ( md_digest_length( algo ) ); | ||
777 | if ( !helpkey ) | ||
778 | return gpg_err_code_from_errno (errno); | ||
779 | gcry_md_hash_buffer ( algo, helpkey, key, keylen ); | ||
780 | key = helpkey; | ||
781 | keylen = md_digest_length( algo ); | ||
782 | assert ( keylen <= 64 ); | ||
783 | } | ||
784 | |||
785 | memset ( hd->ctx->macpads, 0, 128 ); | ||
786 | ipad = hd->ctx->macpads; | ||
787 | opad = hd->ctx->macpads+64; | ||
788 | memcpy ( ipad, key, keylen ); | ||
789 | memcpy ( opad, key, keylen ); | ||
790 | for (i=0; i < 64; i++ ) | ||
791 | { | ||
792 | ipad[i] ^= 0x36; | ||
793 | opad[i] ^= 0x5c; | ||
794 | } | ||
795 | gcry_free( helpkey ); | ||
796 | |||
797 | return GPG_ERR_NO_ERROR; | ||
798 | } | ||
799 | |||
800 | gcry_error_t | ||
801 | gcry_md_ctl (gcry_md_hd_t hd, int cmd, byte *buffer, size_t buflen) | ||
802 | { | ||
803 | gcry_err_code_t rc = 0; | ||
804 | |||
805 | switch (cmd) | ||
806 | { | ||
807 | case GCRYCTL_FINALIZE: | ||
808 | md_final (hd); | ||
809 | break; | ||
810 | case GCRYCTL_SET_KEY: | ||
811 | rc = gcry_err_code (gcry_md_setkey (hd, buffer, buflen)); | ||
812 | break; | ||
813 | case GCRYCTL_START_DUMP: | ||
814 | md_start_debug (hd, buffer); | ||
815 | break; | ||
816 | case GCRYCTL_STOP_DUMP: | ||
817 | md_stop_debug( hd ); | ||
818 | break; | ||
819 | default: | ||
820 | rc = GPG_ERR_INV_OP; | ||
821 | } | ||
822 | return gcry_error (rc); | ||
823 | } | ||
824 | |||
825 | gcry_error_t | ||
826 | gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen) | ||
827 | { | ||
828 | gcry_err_code_t rc = GPG_ERR_NO_ERROR; | ||
829 | |||
830 | if (! hd->ctx->macpads) | ||
831 | rc = GPG_ERR_CONFLICT; | ||
832 | else | ||
833 | { | ||
834 | rc = prepare_macpads (hd, key, keylen); | ||
835 | if (! rc) | ||
836 | gcry_md_reset (hd); | ||
837 | } | ||
838 | |||
839 | return gcry_error (rc); | ||
840 | } | ||
841 | |||
842 | |||
843 | /**************** | ||
844 | * if ALGO is null get the digest for the used algo (which should be only one) | ||
845 | */ | ||
846 | static byte * | ||
847 | md_read( gcry_md_hd_t a, int algo ) | ||
848 | { | ||
849 | GcryDigestEntry *r = a->ctx->list; | ||
850 | |||
851 | if (! algo) | ||
852 | { | ||
853 | /* return the first algorithm */ | ||
854 | if (r && r->next) | ||
855 | log_debug("more than algorithm in md_read(0)\n"); | ||
856 | return r->digest->read( &r->context.c ); | ||
857 | } | ||
858 | else | ||
859 | { | ||
860 | for (r = a->ctx->list; r; r = r->next) | ||
861 | if (r->module->mod_id == algo) | ||
862 | return r->digest->read (&r->context.c); | ||
863 | } | ||
864 | BUG(); | ||
865 | return NULL; | ||
866 | } | ||
867 | |||
868 | /* | ||
869 | * Read out the complete digest, this function implictly finalizes | ||
870 | * the hash. | ||
871 | */ | ||
872 | byte * | ||
873 | gcry_md_read (gcry_md_hd_t hd, int algo) | ||
874 | { | ||
875 | gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0); | ||
876 | return md_read (hd, algo); | ||
877 | } | ||
878 | |||
879 | /**************** | ||
880 | * This function combines md_final and md_read but keeps the context | ||
881 | * intact. This function can be used to calculate intermediate | ||
882 | * digests. The digest is copied into buffer and the digestlength is | ||
883 | * returned. If buffer is NULL only the needed size for buffer is returned. | ||
884 | * buflen gives the max size of buffer. If the buffer is too shourt to | ||
885 | * hold the complete digest, the buffer is filled with as many bytes are | ||
886 | * possible and this value is returned. | ||
887 | */ | ||
888 | #if 0 | ||
889 | static int | ||
890 | md_digest( gcry_md_hd_t a, int algo, byte *buffer, int buflen ) | ||
891 | { | ||
892 | struct md_digest_list_s *r = NULL; | ||
893 | char *context; | ||
894 | char *digest; | ||
895 | |||
896 | if( a->bufpos ) | ||
897 | md_write( a, NULL, 0 ); | ||
898 | |||
899 | if( !algo ) { /* return digest for the first algorithm */ | ||
900 | if( (r=a->ctx->list) && r->next ) | ||
901 | log_debug("more than algorithm in md_digest(0)\n"); | ||
902 | } | ||
903 | else { | ||
904 | for(r=a->ctx->list; r; r = r->next ) | ||
905 | if( r->algo == algo ) | ||
906 | break; | ||
907 | } | ||
908 | if( !r ) | ||
909 | BUG(); | ||
910 | |||
911 | if( !buffer ) | ||
912 | return r->mdlen; | ||
913 | |||
914 | /* I don't want to change the interface, so I simply work on a copy | ||
915 | * of the context (extra overhead - should be fixed)*/ | ||
916 | context = a->ctx->secure ? gcry_xmalloc_secure( r->contextsize ) | ||
917 | : gcry_xmalloc( r->contextsize ); | ||
918 | memcpy( context, r->context.c, r->contextsize ); | ||
919 | (*r->digest->final)( context ); | ||
920 | digest = (*r->digest->read)( context ); | ||
921 | |||
922 | if( buflen > r->mdlen ) | ||
923 | buflen = r->mdlen; | ||
924 | memcpy( buffer, digest, buflen ); | ||
925 | |||
926 | gcry_free(context); | ||
927 | return buflen; | ||
928 | } | ||
929 | #endif | ||
930 | |||
931 | /* | ||
932 | * Read out an intermediate digest. Not yet fucntional. | ||
933 | */ | ||
934 | gcry_err_code_t | ||
935 | gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen) | ||
936 | { | ||
937 | /*md_digest ... */ | ||
938 | return GPG_ERR_INTERNAL; | ||
939 | } | ||
940 | |||
941 | |||
942 | /* | ||
943 | * Shortcut function to hash a buffer with a given algo. The only | ||
944 | * guaranteed supported algorithms are RIPE-MD160 and SHA-1. The | ||
945 | * supplied digest buffer must be large enough to store the resulting | ||
946 | * hash. No error is returned, the function will abort on an invalid | ||
947 | * algo. DISABLED_ALGOS are ignored here. */ | ||
948 | void | ||
949 | gcry_md_hash_buffer (int algo, void *digest, | ||
950 | const void *buffer, size_t length) | ||
951 | { | ||
952 | if (algo == GCRY_MD_SHA1) | ||
953 | _gcry_sha1_hash_buffer (digest, buffer, length); | ||
954 | else if (algo == GCRY_MD_RMD160) | ||
955 | _gcry_rmd160_hash_buffer (digest, buffer, length); | ||
956 | else | ||
957 | { | ||
958 | /* For the others we do not have a fast function, so we use the | ||
959 | normal functions. */ | ||
960 | gcry_md_hd_t h; | ||
961 | gpg_err_code_t err = md_open (&h, algo, 0, 0); | ||
962 | if (err) | ||
963 | log_bug ("gcry_md_open failed for algo %d: %s", | ||
964 | algo, gpg_strerror (gcry_error(err))); | ||
965 | md_write (h, (byte *) buffer, length); | ||
966 | md_final (h); | ||
967 | memcpy (digest, md_read (h, algo), md_digest_length (algo)); | ||
968 | md_close (h); | ||
969 | } | ||
970 | } | ||
971 | |||
972 | static int | ||
973 | md_get_algo (gcry_md_hd_t a) | ||
974 | { | ||
975 | GcryDigestEntry *r = a->ctx->list; | ||
976 | |||
977 | if (r && r->next) | ||
978 | log_error("WARNING: more than algorithm in md_get_algo()\n"); | ||
979 | return r ? r->module->mod_id : 0; | ||
980 | } | ||
981 | |||
982 | int | ||
983 | gcry_md_get_algo (gcry_md_hd_t hd) | ||
984 | { | ||
985 | return md_get_algo (hd); | ||
986 | } | ||
987 | |||
988 | |||
989 | /**************** | ||
990 | * Return the length of the digest | ||
991 | */ | ||
992 | static int | ||
993 | md_digest_length (int algorithm) | ||
994 | { | ||
995 | gcry_module_t digest; | ||
996 | int mdlen = 0; | ||
997 | |||
998 | REGISTER_DEFAULT_DIGESTS; | ||
999 | |||
1000 | ath_mutex_lock (&digests_registered_lock); | ||
1001 | digest = _gcry_module_lookup_id (digests_registered, algorithm); | ||
1002 | if (digest) | ||
1003 | { | ||
1004 | mdlen = ((gcry_md_spec_t *) digest->spec)->mdlen; | ||
1005 | _gcry_module_release (digest); | ||
1006 | } | ||
1007 | ath_mutex_unlock (&digests_registered_lock); | ||
1008 | |||
1009 | return mdlen; | ||
1010 | } | ||
1011 | |||
1012 | /**************** | ||
1013 | * Return the length of the digest in bytes. | ||
1014 | * This function will return 0 in case of errors. | ||
1015 | */ | ||
1016 | unsigned int | ||
1017 | gcry_md_get_algo_dlen (int algorithm) | ||
1018 | { | ||
1019 | return md_digest_length (algorithm); | ||
1020 | } | ||
1021 | |||
1022 | |||
1023 | /* Hmmm: add a mode to enumerate the OIDs | ||
1024 | *to make g10/sig-check.c more portable */ | ||
1025 | static const byte * | ||
1026 | md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen) | ||
1027 | { | ||
1028 | const byte *asnoid = NULL; | ||
1029 | gcry_module_t digest; | ||
1030 | |||
1031 | REGISTER_DEFAULT_DIGESTS; | ||
1032 | |||
1033 | ath_mutex_lock (&digests_registered_lock); | ||
1034 | digest = _gcry_module_lookup_id (digests_registered, algorithm); | ||
1035 | if (digest) | ||
1036 | { | ||
1037 | if (asnlen) | ||
1038 | *asnlen = ((gcry_md_spec_t *) digest->spec)->asnlen; | ||
1039 | if (mdlen) | ||
1040 | *mdlen = ((gcry_md_spec_t *) digest->spec)->mdlen; | ||
1041 | asnoid = ((gcry_md_spec_t *) digest->spec)->asnoid; | ||
1042 | _gcry_module_release (digest); | ||
1043 | } | ||
1044 | else | ||
1045 | log_bug ("no ASN.1 OID for md algo %d\n", algorithm); | ||
1046 | ath_mutex_unlock (&digests_registered_lock); | ||
1047 | |||
1048 | return asnoid; | ||
1049 | } | ||
1050 | |||
1051 | |||
1052 | |||
1053 | /**************** | ||
1054 | * Return information about the given cipher algorithm | ||
1055 | * WHAT select the kind of information returned: | ||
1056 | * GCRYCTL_TEST_ALGO: | ||
1057 | *Returns 0 when the specified algorithm is available for use. | ||
1058 | *buffer and nbytes must be zero. | ||
1059 | * GCRYCTL_GET_ASNOID: | ||
1060 | *Return the ASNOID of the algorithm in buffer. if buffer is NULL, only | ||
1061 | *the required length is returned. | ||
1062 | * | ||
1063 | * Note: Because this function is in most cases used to return an | ||
1064 | * integer value, we can make it easier for the caller to just look at | ||
1065 | * the return value. The caller will in all cases consult the value | ||
1066 | * and thereby detecting whether a error occured or not (i.e. while checking | ||
1067 | * the block size) | ||
1068 | */ | ||
1069 | gcry_error_t | ||
1070 | gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes) | ||
1071 | { | ||
1072 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
1073 | |||
1074 | switch (what) | ||
1075 | { | ||
1076 | case GCRYCTL_TEST_ALGO: | ||
1077 | if (buffer || nbytes) | ||
1078 | err = GPG_ERR_INV_ARG; | ||
1079 | else | ||
1080 | err = check_digest_algo (algo); | ||
1081 | break; | ||
1082 | |||
1083 | case GCRYCTL_GET_ASNOID: | ||
1084 | { | ||
1085 | const char unsigned *asn; | ||
1086 | size_t asnlen; | ||
1087 | |||
1088 | asn = md_asn_oid (algo, &asnlen, NULL); | ||
1089 | if (buffer && (*nbytes >= asnlen)) | ||
1090 | { | ||
1091 | memcpy (buffer, asn, asnlen); | ||
1092 | *nbytes = asnlen; | ||
1093 | } | ||
1094 | else if ((! buffer) && nbytes) | ||
1095 | *nbytes = asnlen; | ||
1096 | else | ||
1097 | { | ||
1098 | if (buffer) | ||
1099 | err = GPG_ERR_TOO_SHORT; | ||
1100 | else | ||
1101 | err = GPG_ERR_INV_ARG; | ||
1102 | } | ||
1103 | break; | ||
1104 | } | ||
1105 | |||
1106 | default: | ||
1107 | err = GPG_ERR_INV_OP; | ||
1108 | } | ||
1109 | |||
1110 | return gcry_error (err); | ||
1111 | } | ||
1112 | |||
1113 | |||
1114 | static void | ||
1115 | md_start_debug( gcry_md_hd_t md, char *suffix ) | ||
1116 | { | ||
1117 | static int idx=0; | ||
1118 | char buf[50]; | ||
1119 | |||
1120 | if( md->ctx->debug ) { | ||
1121 | log_debug("Oops: md debug already started\n"); | ||
1122 | return; | ||
1123 | } | ||
1124 | idx++; | ||
1125 | sprintf(buf, "dbgmd-%05d.%.10s", idx, suffix ); | ||
1126 | md->ctx->debug = fopen(buf, "w"); | ||
1127 | if( !md->ctx->debug ) | ||
1128 | log_debug("md debug: can't open %s\n", buf ); | ||
1129 | } | ||
1130 | |||
1131 | static void | ||
1132 | md_stop_debug( gcry_md_hd_t md ) | ||
1133 | { | ||
1134 | if( md->ctx->debug ) { | ||
1135 | if( md->bufpos ) | ||
1136 | md_write( md, NULL, 0 ); | ||
1137 | fclose(md->ctx->debug); | ||
1138 | md->ctx->debug = NULL; | ||
1139 | } | ||
1140 | #ifdef HAVE_U64_TYPEDEF | ||
1141 | { /* a kludge to pull in the __muldi3 for Solaris */ | ||
1142 | volatile u32 a = (u32)(ulong)md; | ||
1143 | volatile u64 b = 42; | ||
1144 | volatile u64 c; | ||
1145 | c = a * b; | ||
1146 | } | ||
1147 | #endif | ||
1148 | } | ||
1149 | |||
1150 | |||
1151 | |||
1152 | /* | ||
1153 | * Return information about the digest handle. | ||
1154 | * GCRYCTL_IS_SECURE: | ||
1155 | *Returns 1 when the handle works on secured memory | ||
1156 | *otherwise 0 is returned. There is no error return. | ||
1157 | * GCRYCTL_IS_ALGO_ENABLED: | ||
1158 | * Returns 1 if the algo is enanled for that handle. | ||
1159 | * The algo must be passed as the address of an int. | ||
1160 | */ | ||
1161 | gcry_error_t | ||
1162 | gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes) | ||
1163 | { | ||
1164 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
1165 | |||
1166 | switch (cmd) | ||
1167 | { | ||
1168 | case GCRYCTL_IS_SECURE: | ||
1169 | *nbytes = h->ctx->secure; | ||
1170 | break; | ||
1171 | |||
1172 | case GCRYCTL_IS_ALGO_ENABLED: | ||
1173 | { | ||
1174 | GcryDigestEntry *r; | ||
1175 | int algo; | ||
1176 | |||
1177 | if ( !buffer || (nbytes && (*nbytes != sizeof (int)))) | ||
1178 | err = GPG_ERR_INV_ARG; | ||
1179 | else | ||
1180 | { | ||
1181 | algo = *(int*)buffer; | ||
1182 | |||
1183 | *nbytes = 0; | ||
1184 | for(r=h->ctx->list; r; r = r->next ) { | ||
1185 | if (r->module->mod_id == algo) | ||
1186 | { | ||
1187 | *nbytes = 1; | ||
1188 | break; | ||
1189 | } | ||
1190 | } | ||
1191 | } | ||
1192 | break; | ||
1193 | } | ||
1194 | |||
1195 | default: | ||
1196 | err = GPG_ERR_INV_OP; | ||
1197 | } | ||
1198 | |||
1199 | return gcry_error (err); | ||
1200 | } | ||
1201 | |||
1202 | gcry_err_code_t | ||
1203 | _gcry_md_init (void) | ||
1204 | { | ||
1205 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
1206 | |||
1207 | REGISTER_DEFAULT_DIGESTS; | ||
1208 | |||
1209 | return err; | ||
1210 | } | ||
1211 | |||
1212 | |||
1213 | int | ||
1214 | gcry_md_is_secure (gcry_md_hd_t a) | ||
1215 | { | ||
1216 | size_t value; | ||
1217 | |||
1218 | if (gcry_md_info (a, GCRYCTL_IS_SECURE, NULL, &value)) | ||
1219 | value = 1; /* It seems to be better to assume secure memory on | ||
1220 | error. */ | ||
1221 | return value; | ||
1222 | } | ||
1223 | |||
1224 | |||
1225 | int | ||
1226 | gcry_md_is_enabled (gcry_md_hd_t a, int algo) | ||
1227 | { | ||
1228 | size_t value; | ||
1229 | |||
1230 | value = sizeof algo; | ||
1231 | if (gcry_md_info (a, GCRYCTL_IS_ALGO_ENABLED, &algo, &value)) | ||
1232 | value = 0; | ||
1233 | return value; | ||
1234 | } | ||
1235 | |||
1236 | /* Get a list consisting of the IDs of the loaded message digest | ||
1237 | modules. If LIST is zero, write the number of loaded message | ||
1238 | digest modules to LIST_LENGTH and return. If LIST is non-zero, the | ||
1239 | first *LIST_LENGTH algorithm IDs are stored in LIST, which must be | ||
1240 | of according size. In case there are less message digest modules | ||
1241 | than *LIST_LENGTH, *LIST_LENGTH is updated to the correct | ||
1242 | number. */ | ||
1243 | gcry_error_t | ||
1244 | gcry_md_list (int *list, int *list_length) | ||
1245 | { | ||
1246 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
1247 | |||
1248 | ath_mutex_lock (&digests_registered_lock); | ||
1249 | err = _gcry_module_list (digests_registered, list, list_length); | ||
1250 | ath_mutex_unlock (&digests_registered_lock); | ||
1251 | |||
1252 | return err; | ||
1253 | } | ||