The big extension module removal.
[gnupg.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 GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG 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 General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * 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 #include "util.h"
28 #include "cipher.h"
29 #include "errors.h"
30 #include "algorithms.h"
31
32 /****************
33  * This structure is used for the list of available algorithms
34  * and for the list of algorithms in MD_HANDLE.
35  */
36 struct md_digest_list_s {
37     struct md_digest_list_s *next;
38     const char *name;
39     int algo;
40     byte *asnoid;
41     int asnlen;
42     int mdlen;
43     void (*init)( void *c );
44     void (*write)( void *c, byte *buf, size_t nbytes );
45     void (*final)( void *c );
46     byte *(*read)( void *c );
47     size_t contextsize; /* allocate this amount of context */
48     PROPERLY_ALIGNED_TYPE context;
49 };
50
51 static struct md_digest_list_s *digest_list;
52
53
54 static struct md_digest_list_s *
55 new_list_item (int algo,
56                const char *(*get_info)( int, size_t*,byte**, int*, int*,
57                                        void (**)(void*),
58                                        void (**)(void*,byte*,size_t),
59                                        void (**)(void*),byte *(**)(void*)))
60 {
61   struct md_digest_list_s *r;
62
63   r = m_alloc_clear (sizeof *r );
64   r->algo = algo;
65   r->name = (*get_info)( algo, &r->contextsize,
66                          &r->asnoid, &r->asnlen, &r->mdlen,
67                          &r->init, &r->write, &r->final, &r->read );
68   if (!r->name ) 
69     {
70       m_free(r);
71       r = NULL;
72     }
73   if (r)
74     {
75       r->next = digest_list;
76       digest_list = r;
77     }
78   return r;
79 }
80
81
82
83 /*
84   Load all available hash algorithms and return true.  Subsequent
85   calls will return 0.  
86  */
87 static int
88 load_digest_module (void)
89 {
90   static int initialized = 0;
91
92   if (initialized)
93     return 0;
94   initialized = 1;
95
96   /* We load them in reverse order so that the most
97      frequently used are the first in the list. */
98   new_list_item (DIGEST_ALGO_TIGER, tiger_get_info); 
99   if (!new_list_item (DIGEST_ALGO_MD5, md5_get_info)) 
100     BUG ();
101   if (!new_list_item (DIGEST_ALGO_RMD160, rmd160_get_info)) 
102     BUG ();
103   if (!new_list_item (DIGEST_ALGO_SHA1, sha1_get_info)) 
104     BUG ();
105
106   return 1;
107 }      
108
109
110 /****************
111  * Map a string to the digest algo */
112 int
113 string_to_digest_algo( const char *string )
114 {
115     struct md_digest_list_s *r;
116
117     do {
118         for(r = digest_list; r; r = r->next )
119             if( !ascii_strcasecmp( r->name, string ) )
120                 return r->algo;
121     } while( !r && load_digest_module () );
122     return 0;
123 }
124
125
126 /****************
127  * Map a digest algo to a string
128  */
129 const char *
130 digest_algo_to_string( int algo )
131 {
132     struct md_digest_list_s *r;
133
134     do {
135         for(r = digest_list; r; r = r->next )
136             if( r->algo == algo )
137                 return r->name;
138     } while( !r && load_digest_module () );
139     return NULL;
140 }
141
142
143 int
144 check_digest_algo( int algo )
145 {
146     struct md_digest_list_s *r;
147
148     do {
149         for(r = digest_list; r; r = r->next )
150             if( r->algo == algo )
151                 return 0;
152     } while( !r && load_digest_module () );
153     return G10ERR_DIGEST_ALGO;
154 }
155
156
157
158 /****************
159  * Open a message digest handle for use with algorithm ALGO.
160  * More algorithms may be added by md_enable(). The initial algorithm
161  * may be 0.
162  */
163 MD_HANDLE
164 md_open( int algo, int secure )
165 {
166     MD_HANDLE hd;
167     int bufsize;
168
169     if( secure ) {
170         bufsize = 512 - sizeof( *hd );
171         hd = m_alloc_secure_clear( sizeof *hd + bufsize );
172     }
173     else {
174         bufsize = 1024 - sizeof( *hd );
175         hd = m_alloc_clear( sizeof *hd + bufsize );
176     }
177
178     hd->bufsize = bufsize+1; /* hd has already one byte allocated */
179     hd->secure = secure;
180     if( algo )
181         md_enable( hd, algo );
182     fast_random_poll();
183     return hd;
184 }
185
186 void
187 md_enable( MD_HANDLE h, int algo )
188 {
189     struct md_digest_list_s *r, *ac;
190
191     for( ac=h->list; ac; ac = ac->next )
192         if( ac->algo == algo )
193             return ; /* already enabled */
194     /* find the algorithm */
195     do {
196         for(r = digest_list; r; r = r->next )
197             if( r->algo == algo )
198                 break;
199     } while( !r && load_digest_module () );
200     if( !r ) {
201         log_error("md_enable: algorithm %d not available\n", algo );
202         return;
203     }
204     /* and allocate a new list entry */
205     ac = h->secure? m_alloc_secure( sizeof *ac + r->contextsize
206                                                - sizeof(r->context) )
207                   : m_alloc( sizeof *ac + r->contextsize
208                                                - sizeof(r->context) );
209     *ac = *r;
210     ac->next = h->list;
211     h->list = ac;
212     /* and init this instance */
213     (*ac->init)( &ac->context.c );
214 }
215
216
217 MD_HANDLE
218 md_copy( MD_HANDLE a )
219 {
220     MD_HANDLE b;
221     struct md_digest_list_s *ar, *br;
222
223     if( a->bufcount )
224         md_write( a, NULL, 0 );
225     b = a->secure ? m_alloc_secure( sizeof *b + a->bufsize - 1 )
226                   : m_alloc( sizeof *b + a->bufsize - 1 );
227     memcpy( b, a, sizeof *a + a->bufsize - 1 );
228     b->list = NULL;
229     b->debug = NULL;
230     /* and now copy the complete list of algorithms */
231     /* I know that the copied list is reversed, but that doesn't matter */
232     for( ar=a->list; ar; ar = ar->next ) {
233         br = a->secure ? m_alloc_secure( sizeof *br + ar->contextsize
234                                                - sizeof(ar->context) )
235                        : m_alloc( sizeof *br + ar->contextsize
236                                                - sizeof(ar->context) );
237         memcpy( br, ar, sizeof(*br) + ar->contextsize
238                                     - sizeof(ar->context) );
239         br->next = b->list;
240         b->list = br;
241     }
242
243     if( a->debug )
244         md_start_debug( b, "unknown" );
245     return b;
246 }
247
248
249 /****************
250  * Reset all contexts and discard any buffered stuff.  This may be used
251  * instead of a md_close(); md_open().
252  */
253 void
254 md_reset( MD_HANDLE a )
255 {
256     struct md_digest_list_s *r;
257
258     a->bufcount = a->finalized = 0;
259     for( r=a->list; r; r = r->next ) {
260         memset( r->context.c, 0, r->contextsize );
261         (*r->init)( &r->context.c );
262     }
263 }
264
265
266 void
267 md_close(MD_HANDLE a)
268 {
269     struct md_digest_list_s *r, *r2;
270
271     if( !a )
272         return;
273     if( a->debug )
274         md_stop_debug(a);
275     for(r=a->list; r; r = r2 ) {
276         r2 = r->next;
277         m_free(r);
278     }
279     m_free(a);
280 }
281
282
283 void
284 md_write( MD_HANDLE a, const byte *inbuf, size_t inlen)
285 {
286     struct md_digest_list_s *r;
287
288     if( a->debug ) {
289         if( a->bufcount && fwrite(a->buffer, a->bufcount, 1, a->debug ) != 1 )
290             BUG();
291         if( inlen && fwrite(inbuf, inlen, 1, a->debug ) != 1 )
292             BUG();
293     }
294     for(r=a->list; r; r = r->next ) {
295         (*r->write)( &r->context.c, a->buffer, a->bufcount );
296         /* Fixme: all ->write fnc should take a const byte* */ 
297         (*r->write)( &r->context.c, (byte*)inbuf, inlen );
298     }
299     a->bufcount = 0;
300 }
301
302
303
304 void
305 md_final(MD_HANDLE a)
306 {
307     struct md_digest_list_s *r;
308
309     if( a->finalized )
310         return;
311
312     if( a->bufcount )
313         md_write( a, NULL, 0 );
314
315     for(r=a->list; r; r = r->next ) {
316         (*r->final)( &r->context.c );
317     }
318     a->finalized = 1;
319 }
320
321
322 /****************
323  * if ALGO is null get the digest for the used algo (which should be only one)
324  */
325 byte *
326 md_read( MD_HANDLE a, int algo )
327 {
328     struct md_digest_list_s *r;
329
330     if( !algo ) {  /* return the first algorithm */
331         if( (r=a->list) ) {
332             if( r->next )
333                 log_debug("more than algorithm in md_read(0)\n");
334             return (*r->read)( &r->context.c );
335         }
336     }
337     else {
338         for(r=a->list; r; r = r->next )
339             if( r->algo == algo )
340                 return (*r->read)( &r->context.c );
341     }
342     BUG();
343     return NULL;
344 }
345
346
347 /****************
348  * This function combines md_final and md_read but keeps the context
349  * intact.  This function can be used to calculate intermediate
350  * digests.  The digest is copied into buffer and the digestlength is
351  * returned.  If buffer is NULL only the needed size for buffer is returned.
352  * buflen gives the max size of buffer. If the buffer is too shourt to
353  * hold the complete digest, the buffer is filled with as many bytes are
354  * possible and this value is returned.
355  */
356 int
357 md_digest( MD_HANDLE a, int algo, byte *buffer, int buflen )
358 {
359     struct md_digest_list_s *r = NULL;
360     char *context;
361     char *digest;
362
363     if( a->bufcount )
364         md_write( a, NULL, 0 );
365
366     if( !algo ) {  /* return digest for the first algorithm */
367         if( (r=a->list) && r->next )
368             log_debug("more than algorithm in md_digest(0)\n");
369     }
370     else {
371         for(r=a->list; r; r = r->next )
372             if( r->algo == algo )
373                 break;
374     }
375     if( !r )
376         BUG();
377
378     if( !buffer )
379         return r->mdlen;
380
381     /* I don't want to change the interface, so I simply work on a copy
382      * the context (extra overhead - should be fixed)*/
383     context = a->secure ? m_alloc_secure( r->contextsize )
384                         : m_alloc( r->contextsize );
385     memcpy( context, r->context.c, r->contextsize );
386     (*r->final)( context );
387     digest = (*r->read)( context );
388
389     if( buflen > r->mdlen )
390         buflen = r->mdlen;
391     memcpy( buffer, digest, buflen );
392
393     m_free(context);
394     return buflen;
395 }
396
397
398 int
399 md_get_algo( MD_HANDLE a )
400 {
401     struct md_digest_list_s *r;
402
403     if( (r=a->list) ) {
404         if( r->next )
405             log_error("WARNING: more than algorithm in md_get_algo()\n");
406         return r->algo;
407     }
408     return 0;
409 }
410
411 /****************
412  * Return the length of the digest
413  */
414 int
415 md_digest_length( int algo )
416 {
417     struct md_digest_list_s *r;
418
419     do {
420         for(r = digest_list; r; r = r->next ) {
421             if( r->algo == algo )
422                 return r->mdlen;
423         }
424     } while( !r && load_digest_module () );
425     log_error("WARNING: no length for md algo %d\n", algo);
426     return 0;
427 }
428
429
430 /* Hmmm: add a mode to enumerate the OIDs
431  *      to make g10/sig-check.c more portable */
432 const byte *
433 md_asn_oid( int algo, size_t *asnlen, size_t *mdlen )
434 {
435     struct md_digest_list_s *r;
436
437     do {
438         for(r = digest_list; r; r = r->next ) {
439             if( r->algo == algo ) {
440                 if( asnlen )
441                     *asnlen = r->asnlen;
442                 if( mdlen )
443                     *mdlen = r->mdlen;
444                 return r->asnoid;
445             }
446         }
447     } while( !r && load_digest_module () );
448     log_bug("no asn for md algo %d\n", algo);
449     return NULL;
450 }
451
452
453 void
454 md_start_debug( MD_HANDLE md, const char *suffix )
455 {
456     static int idx=0;
457     char buf[25];
458
459     if( md->debug ) {
460         log_debug("Oops: md debug already started\n");
461         return;
462     }
463     idx++;
464     sprintf(buf, "dbgmd-%05d" EXTSEP_S "%.10s", idx, suffix );
465     md->debug = fopen(buf, "w");
466     if( !md->debug )
467         log_debug("md debug: can't open %s\n", buf );
468 }
469
470 void
471 md_stop_debug( MD_HANDLE md )
472 {
473     if( md->debug ) {
474         if( md->bufcount )
475             md_write( md, NULL, 0 );
476         fclose(md->debug);
477         md->debug = NULL;
478     }
479 #ifdef HAVE_U64_TYPEDEF
480     {  /* a kludge to pull in the __muldi3 for Solaris */
481        volatile u32 a = (u32)(ulong)md;
482        volatile u64 b = 42;
483        volatile u64 c;
484        c = a * b;
485     }
486 #endif
487 }
488