1 /* md.c - message digest dispatcher
2 * Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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
30 #include "algorithms.h"
34 * This structure is used for the list of available algorithms
35 * and for the list of algorithms in MD_HANDLE.
37 struct md_digest_list_s {
38 struct md_digest_list_s *next;
44 void (*init)( void *c );
45 void (*write)( void *c, byte *buf, size_t nbytes );
46 void (*final)( void *c );
47 byte *(*read)( void *c );
48 size_t contextsize; /* allocate this amount of context */
49 PROPERLY_ALIGNED_TYPE context;
52 static struct md_digest_list_s *digest_list;
55 static struct md_digest_list_s *
56 new_list_item (int algo,
57 const char *(*get_info)( int, size_t*,byte**, int*, int*,
59 void (**)(void*,byte*,size_t),
60 void (**)(void*),byte *(**)(void*)))
62 struct md_digest_list_s *r;
64 r = m_alloc_clear (sizeof *r );
66 r->name = (*get_info)( algo, &r->contextsize,
67 &r->asnoid, &r->asnlen, &r->mdlen,
68 &r->init, &r->write, &r->final, &r->read );
76 r->next = digest_list;
85 Load all available hash algorithms and return true. Subsequent
89 load_digest_module (void)
91 static int initialized = 0;
97 /* We load them in reverse order so that the most
98 frequently used are the first in the list. */
100 if (!new_list_item (DIGEST_ALGO_SHA512, sha512_get_info))
102 if (!new_list_item (DIGEST_ALGO_SHA384, sha384_get_info))
106 if (!new_list_item (DIGEST_ALGO_SHA256, sha256_get_info))
109 if (!new_list_item (DIGEST_ALGO_MD5, md5_get_info))
111 if (!new_list_item (DIGEST_ALGO_RMD160, rmd160_get_info))
113 if (!new_list_item (DIGEST_ALGO_SHA1, sha1_get_info))
121 * Map a string to the digest algo */
123 string_to_digest_algo( const char *string )
125 struct md_digest_list_s *r;
127 /* Hi there. I see you changing that code so you can use the new
128 SHA hashes. Before you do it, please think about it. There
129 are no official releases of any OpenPGP programs that generate
130 these hashes, and we're trying to get a code base that can
131 understand the hashes before we release one that generates
134 if(!ascii_strcasecmp("sha384",string)
135 || !ascii_strcasecmp("sha512",string))
137 log_info(_("digest algorithm `%s' is read-only in this release\n"),
143 for(r = digest_list; r; r = r->next )
144 if( !ascii_strcasecmp( r->name, string ) )
146 } while( !r && load_digest_module () );
148 /* Didn't find it, so try the Hx format */
149 if(string[0]=='H' || string[0]=='h')
156 val=strtol(string,&endptr,10);
157 if(*string!='\0' && *endptr=='\0' && check_digest_algo(val)==0)
165 * Map a digest algo to a string
168 digest_algo_to_string( int algo )
170 struct md_digest_list_s *r;
173 for(r = digest_list; r; r = r->next )
174 if( r->algo == algo )
176 } while( !r && load_digest_module () );
182 check_digest_algo( int algo )
184 struct md_digest_list_s *r;
187 for(r = digest_list; r; r = r->next )
188 if( r->algo == algo )
190 } while( !r && load_digest_module () );
191 return G10ERR_DIGEST_ALGO;
197 * Open a message digest handle for use with algorithm ALGO.
198 * More algorithms may be added by md_enable(). The initial algorithm
202 md_open( int algo, int secure )
208 bufsize = 512 - sizeof( *hd );
209 hd = m_alloc_secure_clear( sizeof *hd + bufsize );
212 bufsize = 1024 - sizeof( *hd );
213 hd = m_alloc_clear( sizeof *hd + bufsize );
216 hd->bufsize = bufsize+1; /* hd has already one byte allocated */
219 md_enable( hd, algo );
225 md_enable( MD_HANDLE h, int algo )
227 struct md_digest_list_s *r, *ac;
229 for( ac=h->list; ac; ac = ac->next )
230 if( ac->algo == algo )
231 return ; /* already enabled */
232 /* find the algorithm */
234 for(r = digest_list; r; r = r->next )
235 if( r->algo == algo )
237 } while( !r && load_digest_module () );
239 log_error("md_enable: algorithm %d not available\n", algo );
242 /* and allocate a new list entry */
243 ac = h->secure? m_alloc_secure( sizeof *ac + r->contextsize
244 - sizeof(r->context) )
245 : m_alloc( sizeof *ac + r->contextsize
246 - sizeof(r->context) );
250 /* and init this instance */
251 (*ac->init)( &ac->context.c );
256 md_copy( MD_HANDLE a )
259 struct md_digest_list_s *ar, *br;
262 md_write( a, NULL, 0 );
263 b = a->secure ? m_alloc_secure( sizeof *b + a->bufsize - 1 )
264 : m_alloc( sizeof *b + a->bufsize - 1 );
265 memcpy( b, a, sizeof *a + a->bufsize - 1 );
268 /* and now copy the complete list of algorithms */
269 /* I know that the copied list is reversed, but that doesn't matter */
270 for( ar=a->list; ar; ar = ar->next ) {
271 br = a->secure ? m_alloc_secure( sizeof *br + ar->contextsize
272 - sizeof(ar->context) )
273 : m_alloc( sizeof *br + ar->contextsize
274 - sizeof(ar->context) );
275 memcpy( br, ar, sizeof(*br) + ar->contextsize
276 - sizeof(ar->context) );
282 md_start_debug( b, "unknown" );
288 * Reset all contexts and discard any buffered stuff. This may be used
289 * instead of a md_close(); md_open().
292 md_reset( MD_HANDLE a )
294 struct md_digest_list_s *r;
296 a->bufcount = a->finalized = 0;
297 for( r=a->list; r; r = r->next ) {
298 memset( r->context.c, 0, r->contextsize );
299 (*r->init)( &r->context.c );
305 md_close(MD_HANDLE a)
307 struct md_digest_list_s *r, *r2;
313 for(r=a->list; r; r = r2 ) {
322 md_write( MD_HANDLE a, const byte *inbuf, size_t inlen)
324 struct md_digest_list_s *r;
327 if( a->bufcount && fwrite(a->buffer, a->bufcount, 1, a->debug ) != 1 )
329 if( inlen && fwrite(inbuf, inlen, 1, a->debug ) != 1 )
332 for(r=a->list; r; r = r->next ) {
333 (*r->write)( &r->context.c, a->buffer, a->bufcount );
334 /* Fixme: all ->write fnc should take a const byte* */
335 (*r->write)( &r->context.c, (byte*)inbuf, inlen );
343 md_final(MD_HANDLE a)
345 struct md_digest_list_s *r;
351 md_write( a, NULL, 0 );
353 for(r=a->list; r; r = r->next ) {
354 (*r->final)( &r->context.c );
361 * if ALGO is null get the digest for the used algo (which should be only one)
364 md_read( MD_HANDLE a, int algo )
366 struct md_digest_list_s *r;
368 if( !algo ) { /* return the first algorithm */
371 log_debug("more than algorithm in md_read(0)\n");
372 return (*r->read)( &r->context.c );
376 for(r=a->list; r; r = r->next )
377 if( r->algo == algo )
378 return (*r->read)( &r->context.c );
386 * This function combines md_final and md_read but keeps the context
387 * intact. This function can be used to calculate intermediate
388 * digests. The digest is copied into buffer and the digestlength is
389 * returned. If buffer is NULL only the needed size for buffer is returned.
390 * buflen gives the max size of buffer. If the buffer is too shourt to
391 * hold the complete digest, the buffer is filled with as many bytes are
392 * possible and this value is returned.
395 md_digest( MD_HANDLE a, int algo, byte *buffer, int buflen )
397 struct md_digest_list_s *r = NULL;
402 md_write( a, NULL, 0 );
404 if( !algo ) { /* return digest for the first algorithm */
405 if( (r=a->list) && r->next )
406 log_debug("more than algorithm in md_digest(0)\n");
409 for(r=a->list; r; r = r->next )
410 if( r->algo == algo )
419 /* I don't want to change the interface, so I simply work on a copy
420 * the context (extra overhead - should be fixed)*/
421 context = a->secure ? m_alloc_secure( r->contextsize )
422 : m_alloc( r->contextsize );
423 memcpy( context, r->context.c, r->contextsize );
424 (*r->final)( context );
425 digest = (*r->read)( context );
427 if( buflen > r->mdlen )
429 memcpy( buffer, digest, buflen );
437 md_get_algo( MD_HANDLE a )
439 struct md_digest_list_s *r;
443 log_error("WARNING: more than algorithm in md_get_algo()\n");
449 /* Returns true if a given algo is in use in a md */
451 md_algo_present( MD_HANDLE a, int algo )
453 struct md_digest_list_s *r=a->list;
467 * Return the length of the digest
470 md_digest_length( int algo )
472 struct md_digest_list_s *r;
475 for(r = digest_list; r; r = r->next ) {
476 if( r->algo == algo )
479 } while( !r && load_digest_module () );
480 log_error("WARNING: no length for md algo %d\n", algo);
485 /* Hmmm: add a mode to enumerate the OIDs
486 * to make g10/sig-check.c more portable */
488 md_asn_oid( int algo, size_t *asnlen, size_t *mdlen )
490 struct md_digest_list_s *r;
493 for(r = digest_list; r; r = r->next ) {
494 if( r->algo == algo ) {
502 } while( !r && load_digest_module () );
503 log_bug("no asn for md algo %d\n", algo);
509 md_start_debug( MD_HANDLE md, const char *suffix )
515 log_debug("Oops: md debug already started\n");
519 sprintf(buf, "dbgmd-%05d" EXTSEP_S "%.10s", idx, suffix );
520 md->debug = fopen(buf, "wb");
522 log_debug("md debug: can't open %s\n", buf );
526 md_stop_debug( MD_HANDLE md )
530 md_write( md, NULL, 0 );
534 #ifdef HAVE_U64_TYPEDEF
535 { /* a kludge to pull in the __muldi3 for Solaris */
536 volatile u32 a = (u32)(ulong)md;