* md.c (load_digest_module): Enlarged checked_algos bitmap.
[libgcrypt.git] / cipher / md.c
1 /* md.c  -  message digest dispatcher
2  * Copyright (C) 1998, 1999, 2002 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 "dynload.h"
31 #include "rmd.h"
32
33
34 static struct {
35   const char *oidstring;
36   int algo;
37 } oid_table[] = {
38   /* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 (sha1WithRSAEncryption) */
39   { "1.2.840.113549.1.1.5",  GCRY_MD_SHA1 },
40   /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 (md5WithRSAEncryption) */
41   { "1.2.840.113549.1.1.4",  GCRY_MD_MD5 },
42   /* iso.member-body.us.x9-57.x9cm.3 (dsaWithSha1)*/
43   { "1.2.840.10040.4.3",     GCRY_MD_SHA1 },
44   /* from NIST's OIW  (sha1) */
45   { "1.3.14.3.2.26",         GCRY_MD_SHA1 },
46   /* rsaSignatureWithripemd160 */
47   { "1.3.36.3.3.1.2",       GCRY_MD_RMD160 },
48   /* RSADSI digestAlgorithm MD5 */
49   { "1.2.840.113549.2.5",   GCRY_MD_MD5 },
50   /* GNU.digestAlgorithm TIGER */
51   { "1.3.6.1.4.1.11591.12.2", GCRY_MD_TIGER },
52   /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */
53   { "1.2.840.113549.2.4", GCRY_MD_MD4 },
54   {NULL}
55 };
56
57
58
59
60 struct md_digest_list_s;
61
62 /* this structure is put right after the GCRY_MD_HD buffer, so that
63  * only one memory block is needed. */
64 struct gcry_md_context {
65     int  magic;
66     int  secure;
67     FILE  *debug;
68     int finalized;
69     struct md_digest_list_s *list;
70     byte *macpads;
71 };
72 #define CTX_MAGIC_NORMAL 0x11071961
73 #define CTX_MAGIC_SECURE 0x16917011
74
75 static const char * digest_algo_to_string( int algo );
76 static int check_digest_algo( int algo );
77 static GCRY_MD_HD md_open( int algo, int secure, int hmac );
78 static int  md_enable( GCRY_MD_HD hd, int algo );
79 static GCRY_MD_HD md_copy( GCRY_MD_HD a );
80 static void md_close(GCRY_MD_HD a);
81 static void md_write( GCRY_MD_HD a, byte *inbuf, size_t inlen);
82 static void md_final(GCRY_MD_HD a);
83 static byte *md_read( GCRY_MD_HD a, int algo );
84 static int md_get_algo( GCRY_MD_HD a );
85 static int md_digest_length( int algo );
86 static const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen );
87 static void md_start_debug( GCRY_MD_HD a, const char *suffix );
88 static void md_stop_debug( GCRY_MD_HD a );
89
90 /****************
91  * This structure is used for the list of available algorithms
92  * and for the list of algorithms in GCRY_MD_HD.
93  */
94 struct md_digest_list_s {
95     struct md_digest_list_s *next;
96     const char *name;
97     int algo;
98     byte *asnoid;
99     int asnlen;
100     int mdlen;
101     void (*init)( void *c );
102     void (*write)( void *c, byte *buf, size_t nbytes );
103     void (*final)( void *c );
104     byte *(*read)( void *c );
105     size_t contextsize; /* allocate this amount of context */
106     PROPERLY_ALIGNED_TYPE context;
107 };
108
109 static struct md_digest_list_s *digest_list;
110
111 #define digitp(p)   (*(p) >= 0 && *(p) <= '9')
112
113
114
115 \f
116 static struct md_digest_list_s *
117 new_list_item( int algo,
118                const char *(*get_info)( int, size_t*,byte**, int*, int*,
119                                        void (**)(void*),
120                                        void (**)(void*,byte*,size_t),
121                                        void (**)(void*),byte *(**)(void*)) )
122 {
123     struct md_digest_list_s *r;
124
125     r = gcry_xcalloc( 1, sizeof *r );
126     r->algo = algo,
127     r->name = (*get_info)( algo, &r->contextsize,
128                            &r->asnoid, &r->asnlen, &r->mdlen,
129                            &r->init, &r->write, &r->final, &r->read );
130     if( !r->name ) {
131         gcry_free(r);
132         r = NULL;
133     }
134     return r;
135 }
136
137
138
139 /****************
140  * Try to load the modules with the requested algorithm
141  * and return true if new modules are available
142  * If req_alog is -1 try to load all digest algorithms.
143  */
144 static int
145 load_digest_module( int req_algo )
146 {
147     static int initialized = 0;
148     static u32 checked_algos[512/32];
149     static int checked_all = 0;
150     struct md_digest_list_s *r;
151     void *context = NULL;
152     int algo;
153     int any = 0;
154     const char *(*get_info)( int, size_t*,byte**, int*, int*,
155                             void (**)(void*),
156                             void (**)(void*,byte*,size_t),
157                             void (**)(void*),byte *(**)(void*));
158
159     if( !initialized ) {
160         _gcry_cipher_modules_constructor();
161         initialized = 1;
162     }
163     algo = req_algo;
164     if( algo > 511 || !algo )
165         return 0; /* algorithm number too high (does not fit into out bitmap)*/
166     if( checked_all )
167         return 0; /* already called with -1 */
168     if( algo < 0 )
169         checked_all = 1;
170     else if( (checked_algos[algo/32] & (1 << (algo%32))) )
171         return 0; /* already checked and not found */
172     else
173         checked_algos[algo/32] |= (1 << (algo%32));
174
175     while( _gcry_enum_gnupgext_digests( &context, &algo, &get_info ) ) {
176         if( req_algo != -1 && algo != req_algo )
177             continue;
178         for(r=digest_list; r; r = r->next )
179             if( r->algo == algo )
180                 break;
181         if( r ) {
182             log_info("skipping digest %d: already loaded\n", algo );
183             continue;
184         }
185         r = new_list_item( algo, get_info );
186         if( ! r ) {
187             log_info("skipping digest %d: no name\n", algo );
188             continue;
189         }
190         /* put it into the list */
191         if( _gcry_log_verbosity( 2 ) )
192             log_info("loaded digest %d\n", algo);
193         r->next = digest_list;
194         digest_list = r;
195         any = 1;
196         if( req_algo != -1 )
197             break;
198     }
199     _gcry_enum_gnupgext_digests( &context, NULL, NULL );
200     return any;
201 }
202
203
204
205 /****************
206  * Map a string to the digest algo
207  */
208 int
209 gcry_md_map_name( const char *string )
210 {
211     struct md_digest_list_s *r;
212     
213     if (!string)
214       return 0;
215
216     /* If the string starts with a digit (optionally prefixed with
217        either "OID." or "oid."), we first look into our table of ASN.1
218        object identifiers to figure out the algorithm */
219     if (digitp (string)
220         || !strncmp (string, "oid.", 4) 
221         || !strncmp (string, "OID.", 4) )
222       {
223         int i;
224         const char *s =  digitp(string)? string : (string+4);
225
226         for (i=0; oid_table[i].oidstring; i++)
227           {
228             if (!strcmp (s, oid_table[i].oidstring))
229               return oid_table[i].algo;
230           }
231       }
232
233     do {
234         for(r = digest_list; r; r = r->next )
235             if( !stricmp( r->name, string ) )
236                 return r->algo;
237     } while( !r && load_digest_module(-1) );
238     return 0;
239 }
240
241
242 /****************
243  * Map a digest algo to a string
244  */
245 static const char *
246 digest_algo_to_string( int algo )
247 {
248     struct md_digest_list_s *r;
249
250     do {
251         for(r = digest_list; r; r = r->next )
252             if( r->algo == algo )
253                 return r->name;
254     } while( !r && load_digest_module( algo ) );
255     return NULL;
256 }
257
258 /****************
259  * This function simply returns the name of the algorithm or some constant
260  * string when there is no algo.  It will never return NULL.
261  * Use  the macro gcry_md_test_algo() to check whether the algorithm
262  * is valid.
263  */
264 const char *
265 gcry_md_algo_name( int algo )
266 {
267     const char *s = digest_algo_to_string( algo );
268     return s? s: "?";
269 }
270
271
272 static int
273 check_digest_algo( int algo )
274 {
275     struct md_digest_list_s *r;
276
277     do {
278         for(r = digest_list; r; r = r->next )
279             if( r->algo == algo )
280                 return 0;
281     } while( !r && load_digest_module(algo) );
282     return GCRYERR_INV_MD_ALGO;
283 }
284
285
286
287 /****************
288  * Open a message digest handle for use with algorithm ALGO.
289  * More algorithms may be added by md_enable(). The initial algorithm
290  * may be 0.
291  */
292 static GCRY_MD_HD
293 md_open( int algo, int secure, int hmac )
294 {
295     GCRY_MD_HD hd;
296     struct gcry_md_context *ctx;
297     int bufsize = secure? 512 : 1024;
298     size_t n;
299
300     /* Allocate a memory area to hold the caller visible buffer with it's
301      * control information and the data required by this module. Set the
302      * context pointer at the beginning to this area.
303      * We have to use this strange scheme because we want to hide the
304      * internal data but have a variable sized buffer.
305      *
306      *  +---+------+---........------+-------------+
307      *  !ctx! bctl !  buffer         ! private     !
308      *  +---+------+---........------+-------------+
309      *    !                           ^
310      *    !---------------------------!
311      *
312      * We have to make sture that private is well aligned.
313      */
314     n = sizeof( struct gcry_md_handle ) + bufsize;
315     n = ((n + sizeof(PROPERLY_ALIGNED_TYPE)-1)
316          / sizeof(PROPERLY_ALIGNED_TYPE) ) * sizeof(PROPERLY_ALIGNED_TYPE);
317
318     /* allocate and set the Context pointer to the private data */
319     hd = secure ? gcry_malloc_secure( n + sizeof( struct gcry_md_context ) )
320                 : gcry_malloc(       n + sizeof( struct gcry_md_context ) );
321     if( !hd ) {
322         set_lasterr( GCRYERR_NO_MEM );
323         return NULL;
324     }
325
326     hd->ctx = ctx = (struct gcry_md_context*)( (char*)hd + n );
327     /* setup the globally visible data (bctl in the diagram)*/
328     hd->bufsize = n - sizeof( struct gcry_md_handle ) + 1;
329     hd->bufpos = 0;
330     /* initialize the private data */
331     memset( hd->ctx, 0, sizeof *hd->ctx );
332     ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
333     ctx->secure = secure;
334     if( hmac ) {
335         ctx->macpads = gcry_malloc_secure( 128 );
336         if( !ctx->macpads ) {
337             md_close( hd );
338             set_lasterr( GCRYERR_NO_MEM );
339             return NULL;
340         }
341     }
342     fast_random_poll(); /* FIXME: should we really do that? */
343     if( algo && md_enable( hd, algo ) ) {
344         md_close( hd );
345         return NULL;
346     }
347     return hd;
348 }
349
350
351 GCRY_MD_HD
352 gcry_md_open (int algo, unsigned int flags)
353 {
354   GCRY_MD_HD hd;
355
356   if (check_digest_algo (algo))
357     {
358       set_lasterr (GCRYERR_INV_MD_ALGO);
359       return NULL;
360     }
361   if ((flags &~ GCRY_MD_FLAG_SECURE) > GCRY_MD_FLAG_SECURE
362       && (flags &~ GCRY_MD_FLAG_HMAC) > GCRY_MD_FLAG_HMAC)
363     {
364       set_lasterr (GCRYERR_INV_ARG);
365       return NULL;
366     }
367   hd = md_open (algo, (flags & GCRY_MD_FLAG_SECURE),
368                 (flags & GCRY_MD_FLAG_HMAC));
369   return hd;
370 }
371
372
373
374 static int
375 md_enable( GCRY_MD_HD hd, int algo )
376 {
377     struct gcry_md_context *h = hd->ctx;
378     struct md_digest_list_s *r, *ac;
379
380     for( ac=h->list; ac; ac = ac->next )
381         if( ac->algo == algo )
382             return 0; /* already enabled */
383     /* find the algorithm */
384     do {
385         for(r = digest_list; r; r = r->next )
386             if( r->algo == algo )
387                 break;
388     } while( !r && load_digest_module( algo ) );
389     if( !r ) {
390         log_debug("md_enable: algorithm %d not available\n", algo );
391         return set_lasterr( GCRYERR_INV_MD_ALGO );
392     }
393     /* and allocate a new list entry */
394     ac = h->secure? gcry_malloc_secure( sizeof *ac + r->contextsize
395                                                - sizeof(r->context) )
396                   : gcry_malloc( sizeof *ac + r->contextsize
397                                                - sizeof(r->context) );
398     if( !ac )
399         return set_lasterr( GCRYERR_NO_MEM );
400
401     *ac = *r;
402     ac->next = h->list;
403     h->list = ac;
404     /* and init this instance */
405     (*ac->init)( &ac->context.c );
406     return 0;
407 }
408
409
410 int
411 gcry_md_enable( GCRY_MD_HD hd, int algo )
412 {
413     return md_enable( hd, algo );
414 }
415
416 static GCRY_MD_HD
417 md_copy( GCRY_MD_HD ahd )
418 {
419     struct gcry_md_context *a = ahd->ctx;
420     struct gcry_md_context *b;
421     GCRY_MD_HD bhd;
422     struct md_digest_list_s *ar, *br;
423     size_t n;
424
425     if( ahd->bufpos )
426         md_write( ahd, NULL, 0 );
427
428     n = (char*)ahd->ctx - (char*)ahd;
429     bhd = a->secure ? gcry_malloc_secure( n + sizeof( struct gcry_md_context ) )
430                     : gcry_malloc(       n + sizeof( struct gcry_md_context ) );
431     if( !bhd ) {
432         set_lasterr( GCRYERR_NO_MEM );
433         return NULL;
434     }
435
436     bhd->ctx = b = (struct gcry_md_context*)( (char*)bhd + n );
437     /* no need to copy the buffer due to the write above */
438     assert( ahd->bufsize == (n - sizeof( struct gcry_md_handle ) + 1) );
439     bhd->bufsize = ahd->bufsize;
440     bhd->bufpos = 0;  assert( !ahd->bufpos );
441     memcpy( b, a, sizeof *a );
442     b->list = NULL;
443     b->debug = NULL;
444     if( a->macpads ) {
445         b->macpads = gcry_malloc_secure( 128 );
446         memcpy( b->macpads, a->macpads, 128 );
447     }
448     /* and now copy the complete list of algorithms */
449     /* I know that the copied list is reversed, but that doesn't matter */
450     for( ar=a->list; ar; ar = ar->next ) {
451         br = a->secure ? gcry_xmalloc_secure( sizeof *br + ar->contextsize
452                                                - sizeof(ar->context) )
453                        : gcry_xmalloc( sizeof *br + ar->contextsize
454                                                - sizeof(ar->context) );
455         memcpy( br, ar, sizeof(*br) + ar->contextsize
456                                     - sizeof(ar->context) );
457         br->next = b->list;
458         b->list = br;
459     }
460
461     if( a->debug )
462         md_start_debug( bhd, "unknown" );
463     return bhd;
464 }
465
466 GCRY_MD_HD
467 gcry_md_copy( GCRY_MD_HD hd )
468 {
469     return md_copy( hd );
470 }
471
472 /****************
473  * Reset all contexts and discard any buffered stuff.  This may be used
474  * instead of a md_close(); md_open().
475  */
476 void
477 gcry_md_reset( GCRY_MD_HD a )
478 {
479     struct md_digest_list_s *r;
480
481     a->bufpos = a->ctx->finalized = 0;
482     for( r=a->ctx->list; r; r = r->next ) {
483         memset( r->context.c, 0, r->contextsize );
484         (*r->init)( &r->context.c );
485     }
486     if( a->ctx->macpads ) {
487         md_write( a, a->ctx->macpads, 64 ); /* inner pad */
488     }
489 }
490
491
492 static void
493 md_close(GCRY_MD_HD a)
494 {
495     struct md_digest_list_s *r, *r2;
496
497     if( !a )
498         return;
499     if( a->ctx->debug )
500         md_stop_debug(a);
501     for(r=a->ctx->list; r; r = r2 ) {
502         r2 = r->next;
503         gcry_free(r);
504     }
505     gcry_free(a->ctx->macpads);
506     gcry_free(a);
507 }
508
509
510 void
511 gcry_md_close( GCRY_MD_HD hd )
512 {
513     md_close( hd );
514 }
515
516
517 static void
518 md_write( GCRY_MD_HD a, byte *inbuf, size_t inlen)
519 {
520     struct md_digest_list_s *r;
521
522     if( a->ctx->debug ) {
523         if( a->bufpos && fwrite(a->buf, a->bufpos, 1, a->ctx->debug ) != 1 )
524             BUG();
525         if( inlen && fwrite(inbuf, inlen, 1, a->ctx->debug ) != 1 )
526             BUG();
527     }
528     for(r=a->ctx->list; r; r = r->next ) {
529         if( a->bufpos )
530             (*r->write)( &r->context.c, a->buf, a->bufpos );
531         (*r->write)( &r->context.c, inbuf, inlen );
532     }
533     a->bufpos = 0;
534 }
535
536
537 void
538 gcry_md_write( GCRY_MD_HD hd, const byte *inbuf, size_t inlen)
539 {
540     md_write( hd, (byte*)inbuf, inlen );
541 }
542
543
544
545 static void
546 md_final(GCRY_MD_HD a)
547 {
548     struct md_digest_list_s *r;
549
550     if( a->ctx->finalized )
551         return;
552
553     if( a->bufpos )
554         md_write( a, NULL, 0 );
555
556     for(r=a->ctx->list; r; r = r->next ) {
557         (*r->final)( &r->context.c );
558     }
559     a->ctx->finalized = 1;
560     if( a->ctx->macpads ) {  /* finish the hmac */
561         int algo = md_get_algo( a );
562         byte *p = md_read( a, algo );
563         size_t dlen = md_digest_length(algo);
564
565         GCRY_MD_HD om = md_open( algo, a->ctx->secure, 0 );
566         if( !om )
567             _gcry_fatal_error( gcry_errno(), NULL );
568         md_write( om, a->ctx->macpads+64, 64 );
569         md_write( om, p, dlen );
570         md_final( om );
571         /* replace our digest with the mac (they have the same size) */
572         memcpy( p, md_read( om, algo ), dlen );
573         md_close( om );
574     }
575 }
576
577
578
579 static int
580 prepare_macpads( GCRY_MD_HD hd, const byte *key, size_t keylen)
581 {
582     int i;
583     int algo = md_get_algo( hd );
584     byte *helpkey = NULL;
585     byte *ipad, *opad;
586
587     if( !algo )
588         return GCRYERR_INV_MD_ALGO; /* i.e. no algo enabled */
589
590     if( keylen > 64 ) {
591         helpkey = gcry_malloc_secure( md_digest_length( algo ) );
592         if( !helpkey )
593             return GCRYERR_NO_MEM;
594         gcry_md_hash_buffer( algo, helpkey, key, keylen );
595         key = helpkey;
596         keylen = md_digest_length( algo );
597         assert( keylen <= 64 );
598     }
599
600     memset( hd->ctx->macpads, 0, 128 );
601     ipad = hd->ctx->macpads;
602     opad = hd->ctx->macpads+64;
603     memcpy( ipad, key, keylen );
604     memcpy( opad, key, keylen );
605     for(i=0; i < 64; i++ ) {
606         ipad[i] ^= 0x36;
607         opad[i] ^= 0x5c;
608     }
609     gcry_free( helpkey );
610     return 0;
611 }
612
613 int
614 gcry_md_ctl( GCRY_MD_HD hd, int cmd, byte *buffer, size_t buflen)
615 {
616     int rc = 0;
617     if( cmd == GCRYCTL_FINALIZE )
618         md_final( hd );
619     else if( cmd == GCRYCTL_SET_KEY ) {
620         rc = gcry_md_setkey ( hd, buffer, buflen );
621     }
622     else if( cmd == GCRYCTL_START_DUMP ) {
623         md_start_debug( hd, buffer );
624     }
625     else if( cmd == GCRYCTL_STOP_DUMP ) {
626         md_stop_debug( hd );
627     }
628     else
629         rc = GCRYERR_INV_OP;
630     return set_lasterr( rc );
631 }
632
633
634 int
635 gcry_md_setkey( GCRY_MD_HD hd, const char *key, size_t keylen )
636 {
637     int rc = 0;
638
639     if( !(hd->ctx->macpads ) )
640         rc = GCRYERR_CONFLICT;
641     else if ( !(rc = prepare_macpads( hd, key, keylen )) )
642         gcry_md_reset( hd );
643
644     return rc;
645 }
646
647
648 /****************
649  * if ALGO is null get the digest for the used algo (which should be only one)
650  */
651 static byte *
652 md_read( GCRY_MD_HD a, int algo )
653 {
654     struct md_digest_list_s *r;
655
656     if( !algo ) {  /* return the first algorithm */
657         if( (r=a->ctx->list) ) {
658             if( r->next )
659                 log_debug("more than algorithm in md_read(0)\n");
660             return (*r->read)( &r->context.c );
661         }
662     }
663     else {
664         for(r=a->ctx->list; r; r = r->next )
665             if( r->algo == algo )
666                 return (*r->read)( &r->context.c );
667     }
668     BUG();
669     return NULL;
670 }
671
672 /****************
673  * Read out the complete digest, this function implictly finalizes
674  * the hash.
675  */
676 byte *
677 gcry_md_read( GCRY_MD_HD hd, int algo )
678 {
679     gcry_md_ctl( hd, GCRYCTL_FINALIZE, NULL, 0 );
680     return md_read( hd, algo);
681 }
682
683
684 /****************
685  * This function combines md_final and md_read but keeps the context
686  * intact.  This function can be used to calculate intermediate
687  * digests.  The digest is copied into buffer and the digestlength is
688  * returned.  If buffer is NULL only the needed size for buffer is returned.
689  * buflen gives the max size of buffer. If the buffer is too shourt to
690  * hold the complete digest, the buffer is filled with as many bytes are
691  * possible and this value is returned.
692  */
693 #if 0
694 static int
695 md_digest( GCRY_MD_HD a, int algo, byte *buffer, int buflen )
696 {
697     struct md_digest_list_s *r = NULL;
698     char *context;
699     char *digest;
700
701     if( a->bufpos )
702         md_write( a, NULL, 0 );
703
704     if( !algo ) {  /* return digest for the first algorithm */
705         if( (r=a->ctx->list) && r->next )
706             log_debug("more than algorithm in md_digest(0)\n");
707     }
708     else {
709         for(r=a->ctx->list; r; r = r->next )
710             if( r->algo == algo )
711                 break;
712     }
713     if( !r )
714         BUG();
715
716     if( !buffer )
717         return r->mdlen;
718
719     /* I don't want to change the interface, so I simply work on a copy
720      * of the context (extra overhead - should be fixed)*/
721     context = a->ctx->secure ? gcry_xmalloc_secure( r->contextsize )
722                              : gcry_xmalloc( r->contextsize );
723     memcpy( context, r->context.c, r->contextsize );
724     (*r->final)( context );
725     digest = (*r->read)( context );
726
727     if( buflen > r->mdlen )
728         buflen = r->mdlen;
729     memcpy( buffer, digest, buflen );
730
731     gcry_free(context);
732     return buflen;
733 }
734 #endif
735
736 /****************
737  * Read out an intermediate digest.
738  */
739 int
740 gcry_md_get( GCRY_MD_HD hd, int algo, byte *buffer, int buflen )
741 {
742     /*md_digest ... */
743     return GCRYERR_INTERNAL;
744 }
745
746
747 /****************
748  * Shortcut function to hash a buffer with a given algo. The only supported
749  * algorithm is RIPE-MD. The supplied digest buffer must be large enough
750  * to store the resulting hash.  No error is returned, the function will
751  * abort on an invalid algo.  DISABLED_ALGOS are ignored here.
752  */
753 void
754 gcry_md_hash_buffer( int algo, char *digest, const char *buffer, size_t length)
755 {
756     if( algo == GCRY_MD_RMD160 )
757         _gcry_rmd160_hash_buffer( digest, buffer, length );
758     else { /* for the others we do not have a fast function, so
759             * we use the normal functions to do it */
760         GCRY_MD_HD h = md_open( algo, 0, 0 );
761         if( !h )
762             BUG(); /* algo not available */
763         md_write( h, (byte*)buffer, length );
764         md_final( h );
765         memcpy( digest, md_read( h, algo ), md_digest_length( algo ) );
766         md_close (h);
767     }
768 }
769
770 static int
771 md_get_algo( GCRY_MD_HD a )
772 {
773     struct md_digest_list_s *r;
774
775     if( (r=a->ctx->list) ) {
776         if( r->next )
777             log_error("WARNING: more than algorithm in md_get_algo()\n");
778         return r->algo;
779     }
780     return 0;
781 }
782
783
784 int
785 gcry_md_get_algo (GCRY_MD_HD hd)
786 {
787   int algo = md_get_algo (hd);
788   if (!algo)
789     {
790       set_lasterr (GCRYERR_INV_MD_ALGO);
791       return 0;
792     }
793   return algo;
794 }
795
796
797 /****************
798  * Return the length of the digest
799  */
800 static int
801 md_digest_length( int algo )
802 {
803     struct md_digest_list_s *r;
804
805     do {
806         for(r = digest_list; r; r = r->next ) {
807             if( r->algo == algo )
808                 return r->mdlen;
809         }
810     } while( !r && load_digest_module( algo ) );
811     return 0;
812 }
813
814 /****************
815  * Return the length of the digest in bytes.
816  * This function will return 0 in case of errors.
817  */
818 unsigned int
819 gcry_md_get_algo_dlen( int algo )
820 {
821     /* we do some very quick checks here */
822     switch( algo )
823     {
824       case GCRY_MD_MD4:
825       case GCRY_MD_MD5: return 16;
826       case GCRY_MD_SHA1:
827       case GCRY_MD_RMD160: return 20;
828       default: {
829             int len = md_digest_length( algo );
830             if( !len )
831                 set_lasterr( GCRYERR_INV_MD_ALGO );
832             return 0;
833         }
834     }
835 }
836
837
838 /* Hmmm: add a mode to enumerate the OIDs
839  *      to make g10/sig-check.c more portable */
840 static const byte *
841 md_asn_oid( int algo, size_t *asnlen, size_t *mdlen )
842 {
843     struct md_digest_list_s *r;
844
845     do {
846         for(r = digest_list; r; r = r->next ) {
847             if( r->algo == algo ) {
848                 if( asnlen )
849                     *asnlen = r->asnlen;
850                 if( mdlen )
851                     *mdlen = r->mdlen;
852                 return r->asnoid;
853             }
854         }
855     } while( !r && load_digest_module( algo ) );
856     log_bug("no asn for md algo %d\n", algo);
857     return NULL;
858 }
859
860
861
862 /****************
863  * Return information about the given cipher algorithm
864  * WHAT select the kind of information returned:
865  *  GCRYCTL_TEST_ALGO:
866  *      Returns 0 when the specified algorithm is available for use.
867  *      buffer and nbytes must be zero.
868  *  GCRYCTL_GET_ASNOID:
869  *      Return the ASNOID of the algorithm in buffer. if buffer is NULL, only
870  *      the required length is returned.
871  *
872  * On error the value -1 is returned and the error reason may be
873  * retrieved by gcry_errno().
874  * Note:  Because this function is in most cases used to return an
875  * integer value, we can make it easier for the caller to just look at
876  * the return value.  The caller will in all cases consult the value
877  * and thereby detecting whether a error occured or not (i.e. while checking
878  * the block size)
879  */
880 int
881 gcry_md_algo_info( int algo, int what, void *buffer, size_t *nbytes)
882 {
883     switch( what ) {
884       case GCRYCTL_TEST_ALGO:
885         if( buffer || nbytes ) {
886             set_lasterr( GCRYERR_INV_ARG );
887             return -1;
888         }
889         if( check_digest_algo( algo ) ) {
890             set_lasterr( GCRYERR_INV_MD_ALGO );
891             return -1;
892         }
893         break;
894
895       case GCRYCTL_GET_ASNOID: {
896             size_t asnlen;
897             const char *asn = md_asn_oid( algo, &asnlen, NULL );
898             if( buffer && *nbytes >= asnlen ) {
899                 memcpy( buffer, asn, asnlen );
900                 *nbytes = asnlen;
901                 return 0;
902             }
903             if( !buffer && nbytes ) {
904                 *nbytes = asnlen;
905                 return 0;
906             }
907             set_lasterr( buffer ? GCRYERR_TOO_SHORT : GCRYERR_INV_ARG );
908             return -1;
909         }
910         break;
911
912       default:
913         set_lasterr( GCRYERR_INV_OP );
914         return -1;
915     }
916     return 0;
917 }
918
919
920
921
922 static void
923 md_start_debug( GCRY_MD_HD md, const char *suffix )
924 {
925     static int idx=0;
926     char buf[25];
927
928     if( md->ctx->debug ) {
929         log_debug("Oops: md debug already started\n");
930         return;
931     }
932     idx++;
933     sprintf(buf, "dbgmd-%05d.%.10s", idx, suffix );
934     md->ctx->debug = fopen(buf, "w");
935     if( !md->ctx->debug )
936         log_debug("md debug: can't open %s\n", buf );
937 }
938
939 static void
940 md_stop_debug( GCRY_MD_HD md )
941 {
942     if( md->ctx->debug ) {
943         if( md->bufpos )
944             md_write( md, NULL, 0 );
945         fclose(md->ctx->debug);
946         md->ctx->debug = NULL;
947     }
948   #ifdef HAVE_U64_TYPEDEF
949     {  /* a kludge to pull in the __muldi3 for Solaris */
950        volatile u32 a = (u32)(ulong)md;
951        volatile u64 b = 42;
952        volatile u64 c;
953        c = a * b;
954     }
955   #endif
956 }
957
958
959
960 /****************
961  * Return information about the digest handle.
962  *  GCRYCTL_IS_SECURE:
963  *      Returns 1 when the handle works on secured memory
964  *      otherwise 0 is returned.  There is no error return.
965  *  GCRYCTL_IS_ALGO_ENABLED:
966  *     Returns 1 if the algo is enanled for that handle.
967  *     The algo must be passed as the address of an int.
968  */
969 int
970 gcry_md_info( GCRY_MD_HD h, int cmd, void *buffer, size_t *nbytes)
971 {
972
973     switch( cmd ) {
974       case GCRYCTL_IS_SECURE:
975         return h->ctx->secure;
976
977       case GCRYCTL_IS_ALGO_ENABLED:
978         {
979             int algo;
980             struct md_digest_list_s *r;
981
982             if (!buffer || (nbytes && *nbytes != sizeof (int))) {
983                 set_lasterr (GCRYERR_INV_ARG);
984                 return -1;
985             }
986             algo = *(int*)buffer;        
987             for(r=h->ctx->list; r; r = r->next ) {
988                 if( r->algo == algo )
989                     return 1;
990             }
991         }
992         break;
993
994       default:
995         set_lasterr( GCRYERR_INV_OP );
996         return -1;
997     }
998     return 0;
999 }
1000