diff options
author | Werner Koch <[email protected]> | 1998-06-16 15:13:28 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 1998-06-16 15:13:28 +0000 |
commit | e6ac5acbbf56ed8995bfa4d5a28160fa3a5d825f (patch) | |
tree | 6ff27595e33dd57d3a8979d245236bd5f404c9b4 /cipher | |
parent | extensions are now working and fixed a lot of bugs (diff) | |
download | gnupg-e6ac5acbbf56ed8995bfa4d5a28160fa3a5d825f.tar.gz gnupg-e6ac5acbbf56ed8995bfa4d5a28160fa3a5d825f.zip |
some more internall structure changes
Diffstat (limited to 'cipher')
-rw-r--r-- | cipher/Makefile.am | 2 | ||||
-rw-r--r-- | cipher/cipher.c | 19 | ||||
-rw-r--r-- | cipher/dynload.c | 62 | ||||
-rw-r--r-- | cipher/dynload.h | 9 | ||||
-rw-r--r-- | cipher/md.c | 371 | ||||
-rw-r--r-- | cipher/md.h | 74 | ||||
-rw-r--r-- | cipher/md5.c | 55 | ||||
-rw-r--r-- | cipher/md5.h | 20 | ||||
-rw-r--r-- | cipher/pubkey.c | 29 | ||||
-rw-r--r-- | cipher/rmd.h | 20 | ||||
-rw-r--r-- | cipher/rmd160.c | 46 | ||||
-rw-r--r-- | cipher/sha1.c | 48 | ||||
-rw-r--r-- | cipher/sha1.h | 21 | ||||
-rw-r--r-- | cipher/tiger.c | 121 |
14 files changed, 607 insertions, 290 deletions
diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 2cb4ddc41..d0c0202c9 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -9,7 +9,6 @@ noinst_LIBRARIES = libcipher.a libcipher_a_SOURCES = cipher.c \ pubkey.c \ md.c \ - md.h \ dynload.c \ dynload.h \ blowfish.c \ @@ -19,7 +18,6 @@ libcipher_a_SOURCES = cipher.c \ elgamal.c \ elgamal.h \ md5.c \ - md5.h \ primegen.c \ random.h \ random.c \ diff --git a/cipher/cipher.c b/cipher/cipher.c index cedcb37af..df38850ad 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -35,7 +35,7 @@ #define STD_BLOCKSIZE 8 -#define TABLE_SIZE 20 +#define TABLE_SIZE 10 struct cipher_table_s { const char *name; @@ -79,13 +79,9 @@ static void setup_cipher_table() { - static int initialized = 0; int i; size_t blocksize; - if( initialized ) - return; - i = 0; cipher_table[i].algo = CIPHER_ALGO_BLOWFISH; cipher_table[i].name = blowfish_get_info( cipher_table[i].algo, @@ -131,7 +127,6 @@ setup_cipher_table() for( ; i < TABLE_SIZE; i++ ) cipher_table[i].name = NULL; - initialized = 1; } @@ -142,6 +137,7 @@ static int load_cipher_modules() { static int done = 0; + static int initialized = 0; void *context = NULL; struct cipher_table_s *ct; int ct_idx; @@ -150,6 +146,12 @@ load_cipher_modules() const char *name; int any = 0; + if( !initialized ) { + setup_cipher_table(); /* load static modules on the first call */ + initialized = 1; + return 1; + } + if( done ) return 0; done = 1; @@ -208,7 +210,6 @@ string_to_cipher_algo( const char *string ) int i; const char *s; - setup_cipher_table(); do { for(i=0; (s=cipher_table[i].name); i++ ) if( !stricmp( s, string ) ) @@ -225,7 +226,6 @@ cipher_algo_to_string( int algo ) { int i; - setup_cipher_table(); do { for(i=0; cipher_table[i].name; i++ ) if( cipher_table[i].algo == algo ) @@ -242,7 +242,6 @@ check_cipher_algo( int algo ) { int i; - setup_cipher_table(); do { for(i=0; cipher_table[i].name; i++ ) if( cipher_table[i].algo == algo ) @@ -258,7 +257,6 @@ cipher_get_keylen( int algo ) int i; unsigned len = 0; - setup_cipher_table(); do { for(i=0; cipher_table[i].name; i++ ) { if( cipher_table[i].algo == algo ) { @@ -284,7 +282,6 @@ cipher_open( int algo, int mode, int secure ) CIPHER_HANDLE hd; int i; - setup_cipher_table(); fast_random_poll(); do { for(i=0; cipher_table[i].name; i++ ) diff --git a/cipher/dynload.c b/cipher/dynload.c index 71f0d1959..767372a7e 100644 --- a/cipher/dynload.c +++ b/cipher/dynload.c @@ -22,7 +22,9 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <dlfcn.h> +#ifdef HAVE_DL_DLOPEN + #include <dlfcn.h> +#endif #include "util.h" #include "cipher.h" #include "dynload.h" @@ -86,6 +88,7 @@ register_cipher_extension( const char *fname ) static int load_extension( EXTLIST el ) { + #ifdef USE_DYNAMIC_LINKING char **name; void *sym; const char *err; @@ -143,11 +146,68 @@ load_extension( EXTLIST el ) el->handle = NULL; } el->failed = 1; + #endif /*USE_DYNAMIC_LINKING*/ return -1; } +int +enum_gnupgext_digests( void **enum_context, + int *algo, + const char *(**r_get_info)( int, size_t*,byte**, int*, int*, + void (**)(void*), + void (**)(void*,byte*,size_t), + void (**)(void*),byte *(**)(void*)) ) +{ + EXTLIST r; + ENUMCONTEXT *ctx; + + if( !*enum_context ) { /* init context */ + ctx = m_alloc_clear( sizeof( *ctx ) ); + ctx->r = extensions; + *enum_context = ctx; + } + else if( !algo ) { /* release the context */ + m_free(*enum_context); + *enum_context = NULL; + return 0; + } + else + ctx = *enum_context; + + for( r = ctx->r; r; r = r->next ) { + int class, vers; + + if( r->failed ) + continue; + if( !r->handle && load_extension(r) ) + continue; + /* get a digest info function */ + if( ctx->sym ) + goto inner_loop; + while( (ctx->sym = (*r->enumfunc)(10, &ctx->seq1, &class, &vers)) ) { + void *sym; + /* must check class because enumfunc may be wrong coded */ + if( vers != 1 || class != 10 ) + continue; + inner_loop: + *r_get_info = ctx->sym; + while( (sym = (*r->enumfunc)(11, &ctx->seq2, &class, &vers)) ) { + if( vers != 1 || class != 11 ) + continue; + *algo = *(int*)sym; + ctx->r = r; + return 1; + } + ctx->seq2 = 0; + } + ctx->seq1 = 0; + } + ctx->r = r; + return 0; +} + const char * enum_gnupgext_ciphers( void **enum_context, int *algo, size_t *keylen, size_t *blocksize, size_t *contextsize, diff --git a/cipher/dynload.h b/cipher/dynload.h index 2d829c717..fd87bbeef 100644 --- a/cipher/dynload.h +++ b/cipher/dynload.h @@ -20,6 +20,14 @@ #ifndef G10_CIPHER_DYNLOAD_H #define G10_CIPHER_DYNLOAD_H +int +enum_gnupgext_digests( void **enum_context, + int *algo, + const char *(**r_get_info)( int, size_t*,byte**, int*, int*, + void (**)(void*), + void (**)(void*,byte*,size_t), + void (**)(void*),byte *(**)(void*)) ); + const char * enum_gnupgext_ciphers( void **enum_context, int *algo, size_t *keylen, size_t *blocksize, size_t *contextsize, @@ -28,6 +36,7 @@ enum_gnupgext_ciphers( void **enum_context, int *algo, void (**decrypt)( void *c, byte *outbuf, byte *inbuf ) ); + const char * enum_gnupgext_pubkeys( void **enum_context, int *algo, int *npkey, int *nskey, int *nenc, int *nsig, int *usage, diff --git a/cipher/md.c b/cipher/md.c index b116dd975..3fd7581d7 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +#define DEFINES_MD_HANDLE 1 + #include <config.h> #include <stdio.h> #include <stdlib.h> @@ -26,20 +28,125 @@ #include "util.h" #include "cipher.h" #include "errors.h" +#include "dynload.h" +#include "md5.h" +#include "sha1.h" +#include "rmd.h" +/**************** + * This structure is used for the list of available algorithms + * and for the list of algorithms in MD_HANDLE. + */ +struct md_digest_list_s { + struct md_digest_list_s *next; + const char *name; + int algo; + byte *asnoid; + int asnlen; + int mdlen; + void (*init)( void *c ); + void (*write)( void *c, byte *buf, size_t nbytes ); + void (*final)( void *c ); + byte *(*read)( void *c ); + size_t contextsize; /* allocate this amount of context */ + char context[1]; +}; + +static struct md_digest_list_s *digest_list; + + + +static struct md_digest_list_s * +new_list_item( int algo, + const char *(*get_info)( int, size_t*,byte**, int*, int*, + void (**)(void*), + void (**)(void*,byte*,size_t), + void (**)(void*),byte *(**)(void*)) ) +{ + struct md_digest_list_s *r; + + r = m_alloc_clear( sizeof *r ); + r->algo = algo, + r->name = (*get_info)( algo, &r->contextsize, + &r->asnoid, &r->asnlen, &r->mdlen, + &r->init, &r->write, &r->final, &r->read ); + if( !r->name ) { + m_free(r); + r = NULL; + } + return r; +} -/* Note: the first string is the one used by ascii armor */ -static struct { const char *name; int algo;} digest_names[] = { - { "MD5", DIGEST_ALGO_MD5 }, - { "SHA1", DIGEST_ALGO_SHA1 }, - { "SHA-1", DIGEST_ALGO_SHA1 }, - { "RIPEMD160", DIGEST_ALGO_RMD160 }, - { "RMD160", DIGEST_ALGO_RMD160 }, - { "RMD-160", DIGEST_ALGO_RMD160 }, - { "RIPE-MD-160", DIGEST_ALGO_RMD160 }, - {NULL} }; +/**************** + * Put the static entries into the table. + */ +static void +setup_digest_list() +{ + struct md_digest_list_s *r; + + r = new_list_item( DIGEST_ALGO_MD5, md5_get_info ); + if( r ) { r->next = digest_list; digest_list = r; } + r = new_list_item( DIGEST_ALGO_RMD160, rmd160_get_info ); + if( r ) { r->next = digest_list; digest_list = r; } + + r = new_list_item( DIGEST_ALGO_SHA1, sha1_get_info ); + if( r ) { r->next = digest_list; digest_list = r; } +} + + +/**************** + * Try to load all modules and return true if new modules are available + */ +static int +load_digest_modules() +{ + static int done = 0; + static int initialized = 0; + struct md_digest_list_s *r; + void *context = NULL; + int algo; + int any = 0; + const char *(*get_info)( int, size_t*,byte**, int*, int*, + void (**)(void*), + void (**)(void*,byte*,size_t), + void (**)(void*),byte *(**)(void*)); + + if( !initialized ) { + setup_digest_list(); /* load static modules on the first call */ + initialized = 1; + return 1; + } + + if( done ) + return 0; + done = 1; + + while( enum_gnupgext_digests( &context, &algo, &get_info ) ) { + for(r=digest_list; r; r = r->next ) + if( r->algo == algo ) + break; + if( r ) { + log_info("skipping digest %d: already loaded\n", algo ); + continue; + } + r = new_list_item( algo, get_info ); + if( ! r ) { + log_info("skipping digest %d: no name\n", algo ); + continue; + } + /* put it into the list */ + if( g10_opt_verbose > 1 ) + log_info("loaded digest %d\n", algo); + r->next = digest_list; + digest_list = r; + any = 1; + } + enum_gnupgext_digests( &context, NULL, NULL ); + return any; +} @@ -49,12 +156,13 @@ static struct { const char *name; int algo;} digest_names[] = { int string_to_digest_algo( const char *string ) { - int i; - const char *s; + struct md_digest_list_s *r; - for(i=0; (s=digest_names[i].name); i++ ) - if( !stricmp( s, string ) ) - return digest_names[i].algo; + do { + for(r = digest_list; r; r = r->next ) + if( !stricmp( r->name, string ) ) + return r->algo; + } while( !r && load_digest_modules() ); return 0; } @@ -65,11 +173,13 @@ string_to_digest_algo( const char *string ) const char * digest_algo_to_string( int algo ) { - int i; + struct md_digest_list_s *r; - for(i=0; digest_names[i].name; i++ ) - if( digest_names[i].algo == algo ) - return digest_names[i].name; + do { + for(r = digest_list; r; r = r->next ) + if( r->algo == algo ) + return r->name; + } while( !r && load_digest_modules() ); return NULL; } @@ -77,22 +187,18 @@ digest_algo_to_string( int algo ) int check_digest_algo( int algo ) { - switch( algo ) { - case DIGEST_ALGO_MD5: - case DIGEST_ALGO_RMD160: - case DIGEST_ALGO_SHA1: - return 0; - default: - return G10ERR_DIGEST_ALGO; - } + struct md_digest_list_s *r; + + do { + for(r = digest_list; r; r = r->next ) + if( r->algo == algo ) + return 0; + } while( !r && load_digest_modules() ); + return G10ERR_DIGEST_ALGO; } - - - - /**************** * Open a message digest handle for use with algorithm ALGO. * More algorithms may be added by md_enable(). The initial algorithm @@ -102,7 +208,6 @@ MD_HANDLE md_open( int algo, int secure ) { MD_HANDLE hd; - hd = secure ? m_alloc_secure_clear( sizeof *hd ) : m_alloc_clear( sizeof *hd ); hd->secure = secure; @@ -115,23 +220,29 @@ md_open( int algo, int secure ) void md_enable( MD_HANDLE h, int algo ) { - if( algo == DIGEST_ALGO_MD5 ) { - if( !h->use_md5 ) - md5_init( &h->md5 ); - h->use_md5 = 1; - } - else if( algo == DIGEST_ALGO_RMD160 ) { - if( !h->use_rmd160 ) - rmd160_init( &h->rmd160 ); - h->use_rmd160 = 1; - } - else if( algo == DIGEST_ALGO_SHA1 ) { - if( !h->use_sha1 ) - sha1_init( &h->sha1 ); - h->use_sha1 = 1; + struct md_digest_list_s *r, *ac; + + for( ac=h->list; ac; ac = ac->next ) + if( ac->algo == algo ) + return ; /* already enabled */ + /* find the algorithm */ + do { + for(r = digest_list; r; r = r->next ) + if( r->algo == algo ) + break; + } while( !r && load_digest_modules() ); + if( !r ) { + log_error("md_enable: algorithm %d not available\n", algo ); + return; } - else - log_bug("md_enable(%d)", algo ); + /* and allocate a new list entry */ + ac = h->secure? m_alloc_secure( sizeof *ac + r->contextsize ) + : m_alloc( sizeof *ac + r->contextsize ); + *ac = *r; + ac->next = h->list; + h->list = ac; + /* and init this instance */ + (*ac->init)( &ac->context ); } @@ -139,10 +250,21 @@ MD_HANDLE md_copy( MD_HANDLE a ) { MD_HANDLE b; + struct md_digest_list_s *ar, *br; b = a->secure ? m_alloc_secure( sizeof *b ) : m_alloc( sizeof *b ); memcpy( b, a, sizeof *a ); + b->list = NULL; + /* and now copy the compelte list of algorithms */ + /* I know that the copied list is reversed, but that doesn't matter */ + for( ar=a->list; ar; ar = ar->next ) { + br = a->secure ? m_alloc_secure( sizeof *br + ar->contextsize ) + : m_alloc( sizeof *br + ar->contextsize ); + memcpy( br, ar, sizeof(*br) + ar->contextsize ); + br->next = b->list; + b->list = br; + } return b; } @@ -150,10 +272,16 @@ md_copy( MD_HANDLE a ) void md_close(MD_HANDLE a) { + struct md_digest_list_s *r, *r2; + if( !a ) return; if( a->debug ) md_stop_debug(a); + for(r=a->list; r; r = r2 ) { + r2 = r->next; + m_free(r); + } m_free(a); } @@ -161,23 +289,17 @@ md_close(MD_HANDLE a) void md_write( MD_HANDLE a, byte *inbuf, size_t inlen) { + struct md_digest_list_s *r; + if( a->debug ) { if( a->bufcount && fwrite(a->buffer, a->bufcount, 1, a->debug ) != 1 ) BUG(); if( inlen && fwrite(inbuf, inlen, 1, a->debug ) != 1 ) BUG(); } - if( a->use_rmd160 ) { - rmd160_write( &a->rmd160, a->buffer, a->bufcount ); - rmd160_write( &a->rmd160, inbuf, inlen ); - } - if( a->use_sha1 ) { - sha1_write( &a->sha1, a->buffer, a->bufcount ); - sha1_write( &a->sha1, inbuf, inlen ); - } - if( a->use_md5 ) { - md5_write( &a->md5, a->buffer, a->bufcount ); - md5_write( &a->md5, inbuf, inlen ); + for(r=a->list; r; r = r->next ) { + (*r->write)( &r->context, a->buffer, a->bufcount ); + (*r->write)( &r->context, inbuf, inlen ); } a->bufcount = 0; } @@ -187,14 +309,13 @@ md_write( MD_HANDLE a, byte *inbuf, size_t inlen) void md_final(MD_HANDLE a) { + struct md_digest_list_s *r; + if( a->bufcount ) md_write( a, NULL, 0 ); - if( a->use_rmd160 ) - rmd160_final( &a->rmd160 ); - if( a->use_sha1 ) - sha1_final( &a->sha1 ); - if( a->use_md5 ) - md5_final( &a->md5 ); + + for(r=a->list; r; r = r->next ) + (*r->final)( &r->context ); } @@ -204,34 +325,34 @@ md_final(MD_HANDLE a) byte * md_read( MD_HANDLE a, int algo ) { - if( !algo ) { - if( a->use_rmd160 ) - return rmd160_read( &a->rmd160 ); - if( a->use_sha1 ) - return sha1_read( &a->sha1 ); - if( a->use_md5 ) - return md5_read( &a->md5 ); + struct md_digest_list_s *r; + + if( !algo ) { /* return the first algorithm */ + if( (r=a->list) ) { + if( r->next ) + log_error("warning: more than algorithm in md_read(0)\n"); + return (*r->read)( &r->context ); + } } else { - if( algo == DIGEST_ALGO_RMD160 ) - return rmd160_read( &a->rmd160 ); - if( algo == DIGEST_ALGO_SHA1 ) - return sha1_read( &a->sha1 ); - if( algo == DIGEST_ALGO_MD5 ) - return md5_read( &a->md5 ); + for(r=a->list; r; r = r->next ) + if( r->algo == algo ) + return (*r->read)( &r->context ); } BUG(); + return NULL; } int md_get_algo( MD_HANDLE a ) { - if( a->use_rmd160 ) - return DIGEST_ALGO_RMD160; - if( a->use_sha1 ) - return DIGEST_ALGO_SHA1; - if( a->use_md5 ) - return DIGEST_ALGO_MD5; + struct md_digest_list_s *r; + + if( (r=a->list) ) { + if( r->next ) + log_error("warning: more than algorithm in md_get_algo()\n"); + return r->algo; + } return 0; } @@ -241,67 +362,39 @@ md_get_algo( MD_HANDLE a ) int md_digest_length( int algo ) { - switch( algo ) { - case DIGEST_ALGO_RMD160: - case DIGEST_ALGO_SHA1: - return 20; - default: - return 16; - } + struct md_digest_list_s *r; + + do { + for(r = digest_list; r; r = r->next ) { + if( r->algo == algo ) + return r->mdlen; + } + } while( !r && load_digest_modules() ); + log_error("warning: no length for md algo %d\n", algo); + return 0; } -/* fixme: put the oids in a table and add a mode to enumerate the OIDs - * to make g10/sig-check.c more portable */ +/* fixme: add a mode to enumerate the OIDs + * to make g10/sig-check.c more portable */ const byte * md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ) { - size_t alen; - byte *p; - - if( algo == DIGEST_ALGO_MD5 ) { - static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ - { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, - 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; - alen = DIM(asn); p = asn; - } - else if( algo == DIGEST_ALGO_RMD160 ) { - static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ - { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, - 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; - alen = DIM(asn); p = asn; - } - else if( algo == DIGEST_ALGO_TIGER ) { - /* 40: SEQUENCE { - * 12: SEQUENCE { - * 8: OCTET STRING :54 49 47 45 52 31 39 32 - * 0: NULL - * : } - * 24: OCTET STRING - * : } - * - * By replacing the 5th byte (0x04) with 0x16 we would have; - * 8: IA5String 'TIGER192' - */ - static byte asn[18] = - { 0x30, 0x28, 0x30, 0x0c, 0x04, 0x08, 0x54, 0x49, 0x47, - 0x45, 0x52, 0x31, 0x39, 0x32, 0x05, 0x00, 0x04, 0x18 }; - alen = DIM(asn); p = asn; - } - else if( algo == DIGEST_ALGO_SHA1 ) { - static byte asn[15] = /* Object ID is 1.3.14.3.2.26 */ - { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, - 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; - alen = DIM(asn); p = asn; - } - else - log_bug("md_asn_oid(%d)", algo ); - - if( asnlen ) - *asnlen = alen; - if( mdlen ) - *mdlen = p[alen-1]; - return p; + struct md_digest_list_s *r; + + do { + for(r = digest_list; r; r = r->next ) { + if( r->algo == algo ) { + if( asnlen ) + *asnlen = r->asnlen; + if( mdlen ) + *mdlen = r->mdlen; + return r->asnoid; + } + } + } while( !r && load_digest_modules() ); + log_bug("warning: no asn for md algo %d\n", algo); + return NULL; } diff --git a/cipher/md.h b/cipher/md.h deleted file mode 100644 index b4d690793..000000000 --- a/cipher/md.h +++ /dev/null @@ -1,74 +0,0 @@ -/* md.h - digest functions - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GNUPG. - * - * GNUPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GNUPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifndef G10_MD_H -#define G10_MD_H - -#include <stdio.h> -#include "types.h" -#include "rmd.h" -#include "sha1.h" -#include "md5.h" - -#define MD_BUFFER_SIZE 512 - -typedef struct { - int use_rmd160; - RMD160_CONTEXT rmd160; - int use_sha1; - SHA1_CONTEXT sha1; - #ifdef WITH_TIGER_HASH - int use_tiger; - TIGER_CONTEXT tiger; - #endif - int use_md5; - MD5_CONTEXT md5; - byte buffer[MD_BUFFER_SIZE]; /* primary buffer */ - int bufcount; - int secure; - FILE *debug; -} *MD_HANDLE; - - -#define md_putc(h,c) \ - do { \ - if( (h)->bufcount == MD_BUFFER_SIZE ) \ - md_write( (h), NULL, 0 ); \ - (h)->buffer[(h)->bufcount++] = (c) & 0xff; \ - } while(0) - -/*-- md.c --*/ -int string_to_digest_algo( const char *string ); -const char * digest_algo_to_string( int algo ); -int check_digest_algo( int algo ); -MD_HANDLE md_open( int algo, int secure ); -void md_enable( MD_HANDLE hd, int algo ); -MD_HANDLE md_copy( MD_HANDLE a ); -void md_close(MD_HANDLE a); -void md_write( MD_HANDLE a, byte *inbuf, size_t inlen); -void md_final(MD_HANDLE a); -byte *md_read( MD_HANDLE a, int algo ); -int md_get_algo( MD_HANDLE a ); -int md_digest_length( int algo ); -const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ); -void md_start_debug( MD_HANDLE a, const char *suffix ); -void md_stop_debug( MD_HANDLE a ); -#define md_is_secure(a) ((a)->secure) - -#endif /*G10_MD_H*/ diff --git a/cipher/md5.c b/cipher/md5.c index 7cc22b3bb..72fce0e22 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -38,6 +38,15 @@ #include "memory.h" +typedef struct { + u32 A,B,C,D; /* chaining variables */ + u32 total[2]; + u32 buflen; + char buffer[128]; +} MD5_CONTEXT; + + + #ifdef BIG_ENDIAN_HOST #define SWAP(n) \ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) @@ -49,7 +58,7 @@ 64-byte boundary. (RFC 1321, 3.1: Step 1) */ static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; -void +static void md5_init( MD5_CONTEXT *ctx ) { ctx->A = 0x67452301; @@ -237,7 +246,7 @@ transform( MD5_CONTEXT *ctx, const void *buffer, size_t len ) * account for the presence of each of the characters inBuf[0..inLen-1] * in the message whose digest is being computed. */ -void +static void md5_write( MD5_CONTEXT *ctx, const void *buffer, size_t len) { /* When we already have some bits in our internal buffer concatenate @@ -287,7 +296,7 @@ md5_write( MD5_CONTEXT *ctx, const void *buffer, size_t len) * Returns 16 bytes representing the digest. */ -void +static void md5_final( MD5_CONTEXT *ctx ) { /* Take yet unprocessed bytes into account. */ @@ -317,6 +326,46 @@ md5_final( MD5_CONTEXT *ctx ) ((u32 *)ctx->buffer)[3] = SWAP (ctx->D); } +static byte * +md5_read( MD5_CONTEXT *hd ) +{ + return hd->buffer; +} + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + */ +const char * +md5_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asnlen, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ) +{ + static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ + { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; + + if( algo != 1 ) + return NULL; + + *contextsize = sizeof(MD5_CONTEXT); + *r_asnoid = asn; + *r_asnlen = DIM(asn); + *r_mdlen = 16; + *r_init = (void (*)(void *))md5_init; + *r_write = (void (*)(void *, byte*, size_t))md5_write; + *r_final = (void (*)(void *))md5_final; + *r_read = (byte *(*)(void *))md5_read; + + return "MD5"; +} + /* end of file */ diff --git a/cipher/md5.h b/cipher/md5.h index 817a526a4..a4bcf5c63 100644 --- a/cipher/md5.h +++ b/cipher/md5.h @@ -20,19 +20,15 @@ #ifndef G10_MD5_H #define G10_MD5_H -#include "types.h" -typedef struct { - u32 A,B,C,D; /* chaining variables */ - u32 total[2]; - u32 buflen; - char buffer[128]; -} MD5_CONTEXT; +const char * +md5_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asn_len, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ); -void md5_init( MD5_CONTEXT *ctx ); -void md5_write( MD5_CONTEXT *ctx, const void *buffer, size_t len); -void md5_final( MD5_CONTEXT *ctx); -#define md5_read(h) ( (h)->buffer ) - #endif /*G10_MD5_H*/ diff --git a/cipher/pubkey.c b/cipher/pubkey.c index b18f1c316..f59996c4d 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -33,7 +33,7 @@ #include "dynload.h" -#define TABLE_SIZE 20 +#define TABLE_SIZE 10 struct pubkey_table_s { const char *name; @@ -93,13 +93,8 @@ dummy_get_nbits( int algo, MPI *pkey ) static void setup_pubkey_table() { - - static int initialized = 0; int i; - if( initialized ) - return; - i = 0; pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL; pubkey_table[i].name = elg_get_info( pubkey_table[i].algo, @@ -155,7 +150,6 @@ setup_pubkey_table() for( ; i < TABLE_SIZE; i++ ) pubkey_table[i].name = NULL; - initialized = 1; } @@ -165,6 +159,7 @@ setup_pubkey_table() static int load_pubkey_modules() { + static int initialized = 0; static int done = 0; void *context = NULL; struct pubkey_table_s *ct; @@ -173,6 +168,12 @@ load_pubkey_modules() const char *name; int any = 0; + + if( !initialized ) { + setup_pubkey_table(); + initialized = 1; + return 1; + } if( done ) return 0; done = 1; @@ -237,7 +238,6 @@ string_to_pubkey_algo( const char *string ) int i; const char *s; - setup_pubkey_table(); do { for(i=0; (s=pubkey_table[i].name); i++ ) if( !stricmp( s, string ) ) @@ -255,7 +255,6 @@ pubkey_algo_to_string( int algo ) { int i; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) @@ -280,7 +279,6 @@ check_pubkey_algo2( int algo, unsigned usage ) { int i; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) { @@ -304,7 +302,6 @@ int pubkey_get_npkey( int algo ) { int i; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) @@ -320,7 +317,6 @@ int pubkey_get_nskey( int algo ) { int i; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) @@ -336,7 +332,6 @@ int pubkey_get_nsig( int algo ) { int i; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) @@ -352,7 +347,6 @@ int pubkey_get_nenc( int algo ) { int i; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) @@ -369,7 +363,6 @@ pubkey_nbits( int algo, MPI *pkey ) { int i; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) @@ -384,7 +377,6 @@ pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) { int i; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) @@ -400,7 +392,6 @@ pubkey_check_secret_key( int algo, MPI *skey ) { int i; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) @@ -423,7 +414,6 @@ pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) /* FIXME: check that data fits into the key (in xxx_encrypt)*/ - setup_pubkey_table(); if( DBG_CIPHER ) { log_debug("pubkey_encrypt: algo=%d\n", algo ); for(i=0; i < pubkey_get_npkey(algo); i++ ) @@ -461,7 +451,6 @@ pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) { int i, rc; - setup_pubkey_table(); *result = NULL; /* so the caller can always do an mpi_free */ if( DBG_CIPHER ) { log_debug("pubkey_decrypt: algo=%d\n", algo ); @@ -498,7 +487,6 @@ pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey ) { int i, rc; - setup_pubkey_table(); if( DBG_CIPHER ) { log_debug("pubkey_sign: algo=%d\n", algo ); for(i=0; i < pubkey_get_nskey(algo); i++ ) @@ -532,7 +520,6 @@ pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, { int i, rc; - setup_pubkey_table(); do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) { diff --git a/cipher/rmd.h b/cipher/rmd.h index f3a67243b..64a8a02b5 100644 --- a/cipher/rmd.h +++ b/cipher/rmd.h @@ -20,8 +20,8 @@ #ifndef G10_RMD_H #define G10_RMD_H -#include "types.h" +/* we need this here because random.c must have direct access */ typedef struct { u32 h0,h1,h2,h3,h4; u32 nblocks; @@ -29,11 +29,19 @@ typedef struct { int count; } RMD160_CONTEXT; - -void rmd160_init( RMD160_CONTEXT *c ); -void rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen); -void rmd160_final(RMD160_CONTEXT *hd); +void rmd160_init( RMD160_CONTEXT *hd ); void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ); -#define rmd160_read(h) ( (h)->buf ) + + + +const char * +rmd160_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asn_len, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ); + #endif /*G10_RMD_H*/ diff --git a/cipher/rmd160.c b/cipher/rmd160.c index ad28299fc..e38172498 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -27,6 +27,7 @@ #include "memory.h" #include "rmd.h" + /********************************* * RIPEMD-160 is not patented, see (as of 25.10.97) * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html @@ -411,7 +412,7 @@ transform( RMD160_CONTEXT *hd, byte *data ) /* Update the message digest with the contents * of INBUF with length INLEN. */ -void +static void rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ @@ -443,7 +444,7 @@ rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) /**************** * Apply the rmd160 transform function on the buffer which must have * a length 64 bytes. Do not use this function together with the - * other functions, use rmd160_init to initialize intzernal variables. + * other functions, use rmd160_init to initialize internal variables. * Returns: 16 bytes in buffer with the mixed contentes of buffer. */ void @@ -464,7 +465,7 @@ rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ) /* The routine terminates the computation */ -void +static void rmd160_final( RMD160_CONTEXT *hd ) { u32 t, msb, lsb; @@ -523,4 +524,43 @@ rmd160_final( RMD160_CONTEXT *hd ) #undef X } +static byte * +rmd160_read( RMD160_CONTEXT *hd ) +{ + return hd->buf; +} + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + */ +const char * +rmd160_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asnlen, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ) +{ + static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + + if( algo != 3 ) + return NULL; + + *contextsize = sizeof(RMD160_CONTEXT); + *r_asnoid = asn; + *r_asnlen = DIM(asn); + *r_mdlen = 20; + *r_init = (void (*)(void *))rmd160_init; + *r_write = (void (*)(void *, byte*, size_t))rmd160_write; + *r_final = (void (*)(void *))rmd160_final; + *r_read = (byte *(*)(void *))rmd160_read; + + return "RIPEMD160"; +} diff --git a/cipher/sha1.c b/cipher/sha1.c index 941e69b8d..0a6ffab2c 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -41,6 +41,12 @@ #include "sha1.h" +typedef struct { + u32 h0,h1,h2,h3,h4; + u32 nblocks; + byte buf[64]; + int count; +} SHA1_CONTEXT; #if defined(__GNUC__) && defined(__i386__) @@ -216,7 +222,7 @@ transform( SHA1_CONTEXT *hd, byte *data ) /* Update the message digest with the contents * of INBUF with length INLEN. */ -void +static void sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ @@ -253,7 +259,7 @@ sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen) * Returns: 20 bytes representing the digest. */ -void +static void sha1_final(SHA1_CONTEXT *hd) { u32 t, msb, lsb; @@ -313,4 +319,42 @@ sha1_final(SHA1_CONTEXT *hd) } +static byte * +sha1_read( SHA1_CONTEXT *hd ) +{ + return hd->buf; +} + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + */ +const char * +sha1_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asnlen, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ) +{ + static byte asn[15] = /* Object ID is 1.3.14.3.2.26 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; + if( algo != 2 ) + return NULL; + + *contextsize = sizeof(SHA1_CONTEXT); + *r_asnoid = asn; + *r_asnlen = DIM(asn); + *r_mdlen = 20; + *r_init = (void (*)(void *))sha1_init; + *r_write = (void (*)(void *, byte*, size_t))sha1_write; + *r_final = (void (*)(void *))sha1_final; + *r_read = (byte *(*)(void *))sha1_read; + + return "SHA1"; +} diff --git a/cipher/sha1.h b/cipher/sha1.h index 1a183ffb8..2a47b3e91 100644 --- a/cipher/sha1.h +++ b/cipher/sha1.h @@ -20,19 +20,14 @@ #ifndef G10_SHA1_H #define G10_SHA1_H -#include "types.h" -typedef struct { - u32 h0,h1,h2,h3,h4; - u32 nblocks; - byte buf[64]; - int count; -} SHA1_CONTEXT; - - -void sha1_init( SHA1_CONTEXT *c ); -void sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen); -void sha1_final( SHA1_CONTEXT *hd); -#define sha1_read(h) ( (h)->buf ) +const char * +sha1_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asn_len, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ); #endif /*G10_SHA1_H*/ diff --git a/cipher/tiger.c b/cipher/tiger.c index 11c11b461..2560e8ab7 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -625,7 +625,7 @@ print_data( const char *text, u64 a, u64 b, u64 c, } -void +static void tiger_init( TIGER_CONTEXT *hd ) { hd->a = 0x0123456789abcdefLL; @@ -758,7 +758,7 @@ transform( TIGER_CONTEXT *hd, byte *data ) /* Update the message digest with the contents * of INBUF with length INLEN. */ -void +static void tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ @@ -792,7 +792,7 @@ tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen) /* The routine terminates the computation */ -void +static void tiger_final( TIGER_CONTEXT *hd ) { u32 t, msb, lsb; @@ -851,3 +851,118 @@ tiger_final( TIGER_CONTEXT *hd ) #undef X } +static byte * +tiger_read( TIGER_CONTEXT *hd ) +{ + return hd->buf; +} + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + */ +static const char * +tiger_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asnlen, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ) +{ + /* 40: SEQUENCE { + * 12: SEQUENCE { + * 8: OCTET STRING :54 49 47 45 52 31 39 32 + * 0: NULL + * : } + * 24: OCTET STRING + * : } + * + * By replacing the 5th byte (0x04) with 0x16 we would have; + * 8: IA5String 'TIGER192' + */ + static byte asn[18] = + { 0x30, 0x28, 0x30, 0x0c, 0x04, 0x08, 0x54, 0x49, 0x47, + 0x45, 0x52, 0x31, 0x39, 0x32, 0x05, 0x00, 0x04, 0x18 }; + + if( algo != 6 ) + return NULL; + + *contextsize = sizeof(TIGER_CONTEXT); + *r_asnoid = asn; + *r_asnlen = DIM(asn); + *r_mdlen = 24; + *r_init = (void (*)(void *))tiger_init; + *r_write = (void (*)(void *, byte*, size_t))tiger_write; + *r_final = (void (*)(void *))tiger_final; + *r_read = (byte *(*)(void *))tiger_read; + + return "TIGER"; +} + + + +const char * const gnupgext_version = "TIGER ($Revision$)"; + +static struct { + int class; + int version; + int value; + void (*func)(void); +} func_table[] = { + { 10, 1, 0, (void(*)(void))tiger_get_info }, + { 11, 1, 6 }, +}; + + + +/**************** + * Enumerate the names of the functions together with informations about + * this function. Set sequence to an integer with a initial value of 0 and + * do not change it. + * If what is 0 all kind of functions are returned. + * Return values: class := class of function: + * 10 = message digest algorithm info function + * 11 = integer with available md algorithms + * 20 = cipher algorithm info function + * 21 = integer with available cipher algorithms + * 30 = public key algorithm info function + * 31 = integer with available pubkey algorithms + * version = interface version of the function/pointer + * (currently this is 1 for all functions) + */ +void * +gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) +{ + void *ret; + int i = *sequence; + + /*log_info("gnupgext_enum_func in rsa+idea called what=%d i=%d: ", what, i);*/ + do { + if( i >= DIM(func_table) || i < 0 ) { + /*fprintf(stderr, "failed\n");*/ + return NULL; + } + *class = func_table[i].class; + *vers = func_table[i].version; + switch( *class ) { + case 11: + case 21: + case 31: + ret = &func_table[i].value; + break; + default: + ret = func_table[i].func; + break; + } + i++; + } while( what && what != *class ); + + *sequence = i; + /*fprintf(stderr, "success\n");*/ + return ret; +} + + |