diff --git a/ChangeLog b/ChangeLog index ff660371c..b14febd69 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2002-08-02 Werner Koch + + * configure.ac: Removed all extension stuff but keep the tests for + dlopen. We don't need to figure out the flags required. All + stuff is now statically loaded. + 2002-07-30 David Shaw * README, configure.ac: --with-exec-path is now clarified into diff --git a/NEWS b/NEWS index e5b52bba0..20b4e11dc 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Noteworthy changes in version 1.1.91 ------------------------------------------------- + * All modules are now linked statically; the --load-extension + option is in general not useful anymore. The only exception is + to specify the deprecated idea cipher. + * When using --batch with one of the --delete-key commands, the key must be specified by fingerprint. See the man page for details. diff --git a/README b/README index cd5216c43..0e2f3059b 100644 --- a/README +++ b/README @@ -460,7 +460,7 @@ --enable-static-rnd= Force the use of the random byte gathering module . Default is either to use /dev/random - or the standard Uix module. Value for name: + or the standard Unix module. Value for name: egd - Use the module which accesses the Entropy Gathering Daemon. See the webpages for more information about it. @@ -469,8 +469,6 @@ linux - Use the module which accesses /dev/random. This is the first choice and the default one for GNU/Linux or *BSD. - none - Do not linkl any module in but rely on - a dynmically loaded modules. --with-egd-socket= This is only used when EGD is used as random @@ -501,7 +499,8 @@ --disable-dynload If you have problems with dynamic loading, this - option disables all dynamic loading stuff. + option disables all dynamic loading stuff. Note + that the use of dynamic linking is very limited. --disable-asm Do not use assembler modules. It is not possible diff --git a/THANKS b/THANKS index a87a0238e..1bb173a68 100644 --- a/THANKS +++ b/THANKS @@ -23,6 +23,7 @@ Cees van de Griend cees-list@griend.xs4all.nl Charles Levert charles@comm.polymtl.ca Chip Salzenberg chip@valinux.com Chris Adams cmadams@hiwaay.net +Christian Biere christianbiere@gmx.de Christian Kurz shorty@debian.org Christian von Roques roques@pond.sub.org Christopher Oliver oliver@fritz.traverse.net diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 77efc4449..6599a51bc 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,41 @@ +2002-08-03 Werner Koch + + * rndegd.c (do_read): Handle case when read returns 0 to avoid + gpg hanging when EGD died. By Christian Biere. + +2002-08-02 Werner Koch + + The big extension removal. + + * Makefile.am: Removed all extension stuff. + * dynload.c: Removed everything except for + register_cipher_extension. + (dynload_enum_module_names): New. + * dynload.h: Removed. + * random.c (getfnc_gather_random,getfnc_fast_random_poll): + New. Replaced all dynload functions with these ones. + * rndunix.c (rndunix_gather_random): Renamed from + gather_random. Made global. Removed all dynload stuff. + * rndlinux.c (rndlinux_gather_random): Likewise. + * rndegd.c (rndegd_gather_random): Likewise. + * rndw32.c (rndw32_gather_random) + (rndw32_gather_random_fast): Likewise. Also removed the unsued + entropy dll code. + * md.c (new_list_item): Changed return value to indicate whether + an algorithms was loaded. + (load_digest_module): Simplified by removing all the dynload code. + * algorithms.h: New. + * md5.c (md5_get_info): Made global. Removed all dynload stuff. + * rmd160.c (rmd160_get_info): Likewise. + * sha1.c (sha1_get_info): Likewise. + * tiger.c (tiger_get_info): Likewise. Return NULL if we can't use + this module. + * idea-stub.c: New. + * blowfish.h (idea_get_info): Add prototype. + * cipher.c (setup_cipher_table): Try to load IDEA. + (load_cipher_modules): Removed all dynload code. + * pubkey.c (load_pubkey_modules): Removed the dynloading code. + 2002-07-25 David Shaw * random.c: "warning" -> "WARNING" diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 83e81877e..59aae94d7 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -18,39 +18,14 @@ ## Process this file with automake to produce Makefile.in - INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl noinst_LIBRARIES = libcipher.a -# The configure script greps the module names from the EXTRA_PROGRAMS line -EXTRA_PROGRAMS = rndlinux rndunix rndegd rndw32 sha1 rmd160 md5 tiger - -EXTRA_rndlinux_SOURCES = rndlinux.c -EXTRA_rndunix_SOURCES = rndunix.c -EXTRA_rndegd_SOURCES = rndegd.c -EXTRA_rndw32_SOURCES = rndw32.c -EXTRA_md5_SOURCES = md5.c -EXTRA_rmd160_SOURCES = rmd160.c -EXTRA_sha1_SOURCES = sha1.c -EXTRA_tiger_SOURCES = tiger.c - - -if ENABLE_GNUPG_EXTENSIONS -pkglib_PROGRAMS = @DYNAMIC_CIPHER_MODS@ -else -pkglib_PROGRAMS = -endif - - -DYNLINK_MOD_CFLAGS = -DIS_MODULE @DYNLINK_MOD_CFLAGS@ - -#libcipher_a_LDFLAGS = libcipher_a_SOURCES = cipher.c \ pubkey.c \ md.c \ dynload.c \ - dynload.h \ bithelp.h \ des.c \ des.h \ @@ -72,43 +47,22 @@ libcipher_a_SOURCES = cipher.c \ dsa.c \ g10c.c \ smallprime.c \ - construct.c + algorithms.h \ + rndlinux.c \ + rndunix.c \ + rndegd.c \ + rndw32.c \ + md5.c \ + rmd160.c \ + sha1.c \ + tiger.c -# configure creates the constructor file -BUILT_SOURCES = construct.c -DISTCLEANFILES = construct.c +EXTRA_libcipher_a_SOURCES = idea-stub.c -libcipher_a_DEPENDENCIES = @STATIC_CIPHER_OBJS@ -libcipher_a_LIBADD = @STATIC_CIPHER_OBJS@ - - -# If I remember it correct, automake 1.4 has a feature to set -# fooFLAGS depending on the program. So we should check it out. - -tiger$(EXEEXT): $(srcdir)/tiger.c - `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o tiger $(srcdir)/tiger.c | \ - sed -e 's/-O[2-9s]*/-O/g' ` +libcipher_a_DEPENDENCIES = @IDEA_O@ +libcipher_a_LIBADD = @IDEA_O@ tiger.o: $(srcdir)/tiger.c `echo $(COMPILE) -c $(srcdir)/tiger.c | sed -e 's/-O[2-9s]*/-O1/g' ` -#twofish: $(srcdir)/twofish.c -# `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o twofish $(srcdir)/twofish.c | \ -# sed -e 's/-O[0-9s]*/ /g' ` - -twofish: $(srcdir)/twofish.c - $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o twofish $(srcdir)/twofish.c - -#twofish.o: $(srcdir)/twofish.c -# `echo $(COMPILE) -c $(srcdir)/twofish.c | sed -e 's/-O[0-9s]*/ /g' ` - - -rndunix$(EXEEXT): $(srcdir)/rndunix.c - $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndunix $(srcdir)/rndunix.c - -rndlinux$(EXEEXT): $(srcdir)/rndlinux.c - $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndlinux $(srcdir)/rndlinux.c - -rndegd$(EXEEXT): $(srcdir)/rndegd.c - $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndegd $(srcdir)/rndegd.c diff --git a/cipher/algorithms.h b/cipher/algorithms.h new file mode 100644 index 000000000..a6b910612 --- /dev/null +++ b/cipher/algorithms.h @@ -0,0 +1,66 @@ +/* algorithms.h - prototypes for algorithm functions. + * Copyright (C) 2002 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 GNUPG_ALGORITHMS_H +#define GNUPG_ALGORITHMS_H 1 + +const char *dynload_enum_module_names (int seq); + + + +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 ) + ); + + +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 ) + ); + +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 ) + ); + +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 ) + ); + + + +#endif /*GNUPG_ALGORITHMS_H*/ diff --git a/cipher/blowfish.h b/cipher/blowfish.h index bed034c73..46e302288 100644 --- a/cipher/blowfish.h +++ b/cipher/blowfish.h @@ -41,7 +41,7 @@ twofish_get_info( int algo, size_t *keylen, void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) ); -/* this is just a kludge for the time we have not yet chnaged the cipher +/* this is just a kludge for the time we have not yet changed the cipher * stuff to the scheme we use for random and digests */ const char * rijndael_get_info( int algo, size_t *keylen, @@ -51,4 +51,12 @@ rijndael_get_info( int algo, size_t *keylen, void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) ); +const char * +idea_get_info( int algo, size_t *keylen, + size_t *blocksize, size_t *contextsize, + int (**setkeyf)( void *c, byte *key, unsigned keylen ), + void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), + void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) + ); + #endif /*G10_BLOWFISH_H*/ diff --git a/cipher/cipher.c b/cipher/cipher.c index 2744f041a..761ec9b99 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -1,5 +1,5 @@ /* cipher.c - cipher dispatcher - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -30,7 +30,6 @@ #include "des.h" #include "blowfish.h" #include "cast5.h" -#include "dynload.h" #define MAX_BLOCKSIZE 16 @@ -162,6 +161,16 @@ setup_cipher_table(void) if( !cipher_table[i].name ) BUG(); i++; + cipher_table[i].algo = CIPHER_ALGO_IDEA; + cipher_table[i].name = idea_get_info( cipher_table[i].algo, + &cipher_table[i].keylen, + &cipher_table[i].blocksize, + &cipher_table[i].contextsize, + &cipher_table[i].setkey, + &cipher_table[i].encrypt, + &cipher_table[i].decrypt ); + if (cipher_table[i].name) + i++; /* Note that IDEA is usually no available. */ #ifdef IS_DEVELOPMENT_VERSION cipher_table[i].algo = CIPHER_ALGO_DUMMY; @@ -186,63 +195,15 @@ setup_cipher_table(void) static int load_cipher_modules(void) { - static int done = 0; - static int initialized = 0; - void *context = NULL; - struct cipher_table_s *ct; - int ct_idx; - int i; - const char *name; - int any = 0; + static int initialized = 0; - if( !initialized ) { - cipher_modules_constructor(); - setup_cipher_table(); /* load static modules on the first call */ - initialized = 1; - return 1; + if (!initialized ) + { + setup_cipher_table(); /* load static modules on the first call */ + initialized = 1; + return 1; } - - if( done ) - return 0; - done = 1; - - for(ct_idx=0, ct = cipher_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) { - if( !ct->name ) - break; - } - if( ct_idx >= TABLE_SIZE-1 ) - BUG(); /* table already full */ - /* now load all extensions */ - while( (name = enum_gnupgext_ciphers( &context, &ct->algo, - &ct->keylen, &ct->blocksize, &ct->contextsize, - &ct->setkey, &ct->encrypt, &ct->decrypt)) ) { - if( ct->blocksize != 8 && ct->blocksize != 16 ) { - log_info("skipping cipher %d: unsupported blocksize\n", ct->algo); - continue; - } - for(i=0; cipher_table[i].name; i++ ) - if( cipher_table[i].algo == ct->algo ) - break; - if( cipher_table[i].name ) { - log_info("skipping cipher %d: already loaded\n", ct->algo ); - continue; - } - /* put it into the table */ - if( g10_opt_verbose > 1 ) - log_info("loaded cipher %d (%s)\n", ct->algo, name); - ct->name = name; - ct_idx++; - ct++; - any = 1; - /* check whether there are more available table slots */ - if( ct_idx >= TABLE_SIZE-1 ) { - log_info("cipher table full; ignoring other extensions\n"); - break; - } - } - enum_gnupgext_ciphers( &context, NULL, NULL, NULL, NULL, - NULL, NULL, NULL ); - return any; + return 0; } diff --git a/cipher/dynload.c b/cipher/dynload.c index 09cd1366a..38c6a0c35 100644 --- a/cipher/dynload.c +++ b/cipher/dynload.c @@ -1,5 +1,5 @@ /* dynload.c - load cipher extensions - * Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,139 +23,22 @@ #include #include #include -#ifdef HAVE_DL_DLOPEN - #include -#elif defined(HAVE_DLD_DLD_LINK) - #include -#elif defined(HAVE_DL_SHL_LOAD) - #include - #include -#endif -#ifdef __MINGW32__ - #include -#endif #include "util.h" #include "cipher.h" -#include "dynload.h" - -#ifdef WITH_SYMBOL_UNDERSCORE - #define SYMBOL_VERSION "_gnupgext_version" - #define SYMBOL_ENUM "_gnupgext_enum_func" -#else - #define SYMBOL_VERSION "gnupgext_version" - #define SYMBOL_ENUM "gnupgext_enum_func" -#endif - - -#ifndef RTLD_NOW - #define RTLD_NOW 1 -#endif - -#ifdef HAVE_DL_SHL_LOAD /* HPUX has shl_load instead of dlopen */ -#define HAVE_DL_DLOPEN -#define dlopen(PATHNAME,MODE) \ - ((void *) shl_load(PATHNAME, DYNAMIC_PATH | \ - (((MODE) & RTLD_NOW) ? BIND_IMMEDIATE : BIND_DEFERRED), 0L)) -#define dlclose(HANDLE) shl_unload((shl_t) (HANDLE)) -#define dlerror() (errno == 0 ? NULL : strerror(errno)) - -static void * -dlsym(void *handle, char *name) -{ - void *addr; - if (shl_findsym((shl_t *)&handle,name,(short)TYPE_UNDEFINED,&addr) != 0) { - return NULL; - } - return addr; -} -#endif /*HAVE_DL_SHL_LOAD*/ - -#ifdef __MINGW32__ -#define HAVE_DL_DLOPEN -#define USE_DYNAMIC_LINKING - -static int last_error = 0; - -void* -dlopen(const char *pathname, int mode) -{ - void *h = LoadLibrary( pathname ); - if (!h) { - log_error( "LoadLibrary failed ec=%d\n", (int)GetLastError() ); - last_error = 1; - return NULL; - } - return h; -} - -int -dlclose( void *handle ) -{ - last_error = 0; - return FreeLibrary( handle ); -} - -char* -dlerror(void) -{ - static char dlerrstr[10]; - if (last_error) { - sprintf(dlerrstr, "%d", (int)GetLastError() ); - return dlerrstr; - } - return NULL; -} - -void* -dlsym( void *handle, const char *name ) -{ - void *h = GetProcAddress( handle, name ); - if (!h) { - log_error( "GetProcAddress failed ec=%d\n", (int)GetLastError() ); - last_error = 1; - return NULL; - } - return h; -} -#endif /*__MINGW32__*/ - - - +#include "algorithms.h" typedef struct ext_list { struct ext_list *next; - int internal; - #ifdef HAVE_DL_DLOPEN - void *handle; /* handle from dlopen() */ - #else - int handle; /* if the function has been loaded, this is true */ - #endif - int failed; /* already tried but failed */ - void * (*enumfunc)(int, int*, int*, int*); - char *hintstr; /* pointer into name */ char name[1]; } *EXTLIST; static EXTLIST extensions; -typedef struct { - EXTLIST r; - int seq1; - int seq2; - void *sym; - int reqalgo; -} ENUMCONTEXT; - - -#ifdef HAVE_DLD_DLD_LINK -static char *mainpgm_path; -static int did_dld_init; -static int dld_available; -#endif - - -/**************** +/* This is actually not used anymore but we keep a list of already + * set extensions modules here. + * + * Here is the ancient comment: * Register an extension module. The last registered module will * be loaded first. A name may have a list of classes * appended; e.g: @@ -174,10 +57,6 @@ register_cipher_extension( const char *mainpgm, const char *fname ) EXTLIST r, el, intex; char *p, *pe; - #ifdef HAVE_DLD_DLD_LINK - if( !mainpgm_path && mainpgm && *mainpgm ) - mainpgm_path = m_strdup(mainpgm); - #endif if( *fname != DIRSEP_C ) { /* do tilde expansion etc */ char *tmp; @@ -194,12 +73,8 @@ register_cipher_extension( const char *mainpgm, const char *fname ) strcpy(el->name, fname ); } /* check whether we have a class hint */ - if( (p=strchr(el->name,'(')) && (pe=strchr(p+1,')')) && !pe[1] ) { + if( (p=strchr(el->name,'(')) && (pe=strchr(p+1,')')) && !pe[1] ) *p = *pe = 0; - el->hintstr = p+1; - } - else - el->hintstr = NULL; /* check that it is not already registered */ intex = NULL; @@ -209,473 +84,20 @@ register_cipher_extension( const char *mainpgm, const char *fname ) m_free(el); return; } - else if( r->internal ) - intex = r; } /* and register */ - /* we put them after the internal extension modules */ - /* this is so that the external modules do not get loaded */ - /* as soon as the internal modules are requested */ - if( intex ) { - el->next = intex->next; - intex->next = el; - } - else { - el->next = extensions; - extensions = el; - } -} - -void -register_internal_cipher_extension( - const char *module_id, - void * (*enumfunc)(int, int*, int*, int*) - ) -{ - EXTLIST r, el; - - el = m_alloc_clear( sizeof *el + strlen(module_id) ); - strcpy(el->name, module_id ); - el->internal = 1; - - /* check that it is not already registered */ - for(r = extensions; r; r = r->next ) { - if( !compare_filenames(r->name, el->name) ) { - log_info("extension `%s' already registered\n", el->name ); - m_free(el); - return; - } - } - /* and register */ - el->enumfunc = enumfunc; - #ifdef HAVE_DL_DLOPEN - el->handle = (void*)1; - #else - el->handle = 1; - #endif el->next = extensions; extensions = el; } - -static int -load_extension( EXTLIST el ) -{ - #ifdef USE_DYNAMIC_LINKING - char **name; - #ifdef HAVE_DL_DLOPEN - const char *err; - int seq = 0; - int class, vers; - void *sym; - #else - unsigned long addr; - int rc; - #endif - - #ifndef __MINGW32__ - /* make sure we are not setuid */ - if( getuid() != geteuid() ) - log_bug("trying to load an extension while still setuid\n"); - #endif - - /* now that we are not setuid anymore, we can safely load modules */ - #ifdef HAVE_DL_DLOPEN - el->handle = dlopen(el->name, RTLD_NOW); - if( !el->handle ) { - log_error("%s: error loading extension: %s\n", el->name, dlerror() ); - goto failure; - } - name = (char**)dlsym(el->handle, SYMBOL_VERSION); - if( (err=dlerror()) ) { - log_error("%s: not a gnupg extension: %s\n", el->name, err ); - goto failure; - } - #else /* have dld */ - if( !did_dld_init ) { - did_dld_init = 1; - if( !mainpgm_path ) - log_error("DLD is not correctly initialized\n"); - else { - rc = dld_init( dld_find_executable(mainpgm_path) ); - if( rc ) - log_error("DLD init failed: %s\n", dld_strerror(rc) ); - else - dld_available = 1; - } - } - if( !dld_available ) { - log_error("%s: DLD not available\n", el->name ); - goto failure; - } - - rc = dld_link( el->name ); - if( rc ) { - log_error("%s: error loading extension: %s\n", - el->name, dld_strerror(rc) ); - goto failure; - } - addr = dld_get_symbol(SYMBOL_VERSION); - if( !addr ) { - log_error("%s: not a gnupg extension: %s\n", - el->name, dld_strerror(dld_errno) ); - goto failure; - } - name = (char**)addr; - #endif - - if( g10_opt_verbose > 1 ) - log_info("%s: %s%s%s%s\n", el->name, *name, - el->hintstr? " (":"", - el->hintstr? el->hintstr:"", - el->hintstr? ")":""); - - #ifdef HAVE_DL_DLOPEN - sym = dlsym(el->handle, SYMBOL_ENUM); - if( (err=dlerror()) ) { - log_error("%s: invalid gnupg extension: %s\n", el->name, err ); - goto failure; - } - el->enumfunc = (void *(*)(int,int*,int*,int*))sym; - #else /* dld */ - addr = dld_get_func(SYMBOL_ENUM); - if( !addr ) { - log_error("%s: invalid gnupg extension: %s\n", - el->name, dld_strerror(dld_errno) ); - goto failure; - } - rc = dld_function_executable_p(SYMBOL_ENUM); - if( rc ) { - log_error("%s: extension function is not executable: %s\n", - el->name, dld_strerror(rc) ); - goto failure; - } - el->enumfunc = (void *(*)(int,int*,int*,int*))addr; - el->handle = 1; /* mark as usable */ - #endif - - #ifdef HAVE_DL_DLOPEN - if( g10_opt_verbose > 2 ) { - /* list the contents of the module */ - while( (sym = (*el->enumfunc)(0, &seq, &class, &vers)) ) { - if( vers != 1 ) { - log_info("%s: ignoring func with version %d\n",el->name,vers); - continue; - } - switch( class ) { - case 11: - case 21: - case 31: - log_info("%s: provides %s algorithm %d\n", el->name, - class == 11? "md" : - class == 21? "cipher" : "pubkey", - *(int*)sym); - break; - default: - /*log_debug("%s: skipping class %d\n", el->name, class);*/ - break; - } - } - } - #endif - return 0; - - failure: - #ifdef HAVE_DL_DLOPEN - if( el->handle ) { - dlclose(el->handle); - el->handle = NULL; - } - #endif - el->failed = 1; - #endif /*USE_DYNAMIC_LINKING*/ - return -1; -} - -#ifdef __riscos__ -typedef -const char *(*DIGESTS_CAST)(int, size_t*,byte**, int*, int*, - void (**)(void*), - void (**)(void*,byte*,size_t), - void (**)(void*),byte *(**)(void*)); -#endif /* __riscos__ */ - -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; - ctx->reqalgo = *algo; - *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: -#ifndef __riscos__ - *r_get_info = ctx->sym; -#else /* __riscos__ */ - *r_get_info = (DIGESTS_CAST) ctx->sym; -#endif /* __riscos__ */ - 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; -} - -#ifdef __riscos__ -typedef -const char *(*CIPHERS_CAST)(int, size_t*, size_t*, size_t*, - int (**)( void *, byte *, unsigned), - void (**)( void *, byte *, byte *), - void (**)( void *, byte *, byte *)); -#endif /* __riscos__ */ - +/* Return the module name with index SEQ, return NULL as as indication + for end of list. */ const char * -enum_gnupgext_ciphers( void **enum_context, int *algo, - size_t *keylen, size_t *blocksize, size_t *contextsize, - int (**setkeyf)( void *c, byte *key, unsigned keylen ), - void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), - void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) - ) +dynload_enum_module_names (int seq) { - EXTLIST r; - ENUMCONTEXT *ctx; - const char * (*finfo)(int, size_t*, size_t*, size_t*, - int (**)( void *, byte *, unsigned), - void (**)( void *, byte *, byte *), - void (**)( void *, byte *, byte *)); + EXTLIST el = extensions; - 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 NULL; - } - 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 cipher info function */ - if( ctx->sym ) - goto inner_loop; - while( (ctx->sym = (*r->enumfunc)(20, &ctx->seq1, &class, &vers)) ) { - void *sym; - /* must check class because enumfunc may be wrong coded */ - if( vers != 1 || class != 20 ) - continue; - inner_loop: -#ifndef __riscos__ - finfo = ctx->sym; -#else /* __riscos__ */ - finfo = (CIPHERS_CAST) ctx->sym; -#endif /* __riscos__ */ - while( (sym = (*r->enumfunc)(21, &ctx->seq2, &class, &vers)) ) { - const char *algname; - if( vers != 1 || class != 21 ) - continue; - *algo = *(int*)sym; - algname = (*finfo)( *algo, keylen, blocksize, contextsize, - setkeyf, encryptf, decryptf ); - if( algname ) { - ctx->r = r; - return algname; - } - } - ctx->seq2 = 0; - } - ctx->seq1 = 0; - } - ctx->r = r; - return NULL; + for (; el && el->name && seq; el = el->next, seq--) + ; + return el? el->name:NULL; } - -#ifdef __riscos__ -typedef -const char *(*PUBKEYS_CAST)(int, int *, int *, int *, int *, int *, - int (**)(int, unsigned, MPI *, MPI **), - int (**)(int, MPI *), - int (**)(int, MPI *, MPI , MPI *), - int (**)(int, MPI *, MPI *, MPI *), - int (**)(int, MPI *, MPI , MPI *), - int (**)(int, MPI , MPI *, MPI *, - int (*)(void*,MPI), void *), - unsigned (**)( int , MPI *)); -#endif /* __riscos__ */ - -const char * -enum_gnupgext_pubkeys( void **enum_context, int *algo, - int *npkey, int *nskey, int *nenc, int *nsig, int *use, - int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ), - int (**check_secret_key)( int algo, MPI *skey ), - int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ), - int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ), - int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ), - int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ), - unsigned (**get_nbits)( int algo, MPI *pkey ) ) -{ - EXTLIST r; - ENUMCONTEXT *ctx; - const char * (*finfo)( int, int *, int *, int *, int *, int *, - int (**)( int, unsigned, MPI *, MPI **), - int (**)( int, MPI * ), - int (**)( int, MPI *, MPI , MPI * ), - int (**)( int, MPI *, MPI *, MPI * ), - int (**)( int, MPI *, MPI , MPI * ), - int (**)( int, MPI , MPI *, MPI *, - int (*)(void*,MPI), void *), - unsigned (**)( int , MPI * ) ); - - 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 NULL; - } - 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 pubkey info function */ - if( ctx->sym ) - goto inner_loop; - while( (ctx->sym = (*r->enumfunc)(30, &ctx->seq1, &class, &vers)) ) { - void *sym; - if( vers != 1 || class != 30 ) - continue; - inner_loop: -#ifndef __riscos__ - finfo = ctx->sym; -#else /* __riscos__ */ - finfo = (PUBKEYS_CAST) ctx->sym; -#endif /* __riscos__ */ - while( (sym = (*r->enumfunc)(31, &ctx->seq2, &class, &vers)) ) { - const char *algname; - if( vers != 1 || class != 31 ) - continue; - *algo = *(int*)sym; - algname = (*finfo)( *algo, npkey, nskey, nenc, nsig, use, - generate, check_secret_key, encryptf, - decryptf, sign, verify, get_nbits ); - if( algname ) { - ctx->r = r; - return algname; - } - } - ctx->seq2 = 0; - } - ctx->seq1 = 0; - } - ctx->r = r; - return NULL; -} - - -int (* -dynload_getfnc_gather_random())(void (*)(const void*, size_t, int), int, - size_t, int) -{ - EXTLIST r; - void *sym; - - for( r = extensions; r; r = r->next ) { - int seq, class, vers; - - if( r->failed ) - continue; - if( !r->handle && load_extension(r) ) - continue; - seq = 0; - while( (sym = (*r->enumfunc)(40, &seq, &class, &vers)) ) { - if( vers != 1 || class != 40 ) - continue; - return (int (*)(void (*)(const void*, size_t, int), int, - size_t, int))sym; - } - } - return NULL; -} - - -void (* -dynload_getfnc_fast_random_poll())( void (*)(const void*, size_t, int), int) -{ - EXTLIST r; - void *sym; - - for( r = extensions; r; r = r->next ) { - int seq, class, vers; - - if( r->failed ) - continue; - if( !r->handle && load_extension(r) ) - continue; - seq = 0; - while( (sym = (*r->enumfunc)(41, &seq, &class, &vers)) ) { - if( vers != 1 || class != 41 ) - continue; - return (void (*)( void (*)(const void*, size_t, int), int))sym; - } - } - return NULL; -} - diff --git a/cipher/idea-stub.c b/cipher/idea-stub.c new file mode 100644 index 000000000..3a9782037 --- /dev/null +++ b/cipher/idea-stub.c @@ -0,0 +1,187 @@ +/* idea-stub.c - Dummy module for the deprecated IDEA cipher. + * Copyright (C) 2002 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 + */ + +/* IDEA is a patented algorithm and therefore the use of IDEA in + countries where this patent is valid can not be allowed due to the + terms of the GNU General Public License. Those restrictions are + there to help protecting the freedom of software. For more + information on the nonsense of software patents and the general + problem with this, please see http://www.noepatents.org. + + However for research purposes and in certain situations it might be + useful to use this algorithm anyway. + + We provide this stub which will dynload a idea module and is only + used if the configure run did't found statically linked file. + See http://www.gnupg.org/why-not-dea.html for details. +*/ + +#include +#include +#include +#include +#include +#ifdef HAVE_DL_DLOPEN + #include +#endif +#ifdef __MINGW32__ + #include +#endif +#include "util.h" +#include "algorithms.h" + +#ifndef RTLD_NOW + #define RTLD_NOW 1 +#endif + + +#ifdef __MINGW32__ +#define HAVE_DL_DLOPEN +#define USE_DYNAMIC_LINKING + +static int last_error = 0; + +void* +dlopen (const char *pathname, int mode) +{ + void *h = LoadLibrary (pathname); + if (!h) + { + log_error ("LoadLibrary failed ec=%d\n", (int)GetLastError()); + last_error = 1; + return NULL; + } + return h; +} + +int +dlclose ( void *handle ) +{ + last_error = 0; + return FreeLibrary (handle); +} + +char* +dlerror (void) +{ + static char dlerrstr[10]; + if (last_error) + { + sprintf(dlerrstr, "%d", (int)GetLastError() ); + return dlerrstr; + } + return NULL; +} + +void* +dlsym ( void *handle, const char *name ) +{ + void *h = GetProcAddress (handle, name); + if (!h) + { + log_error ("GetProcAddress failed ec=%d\n", (int)GetLastError()); + last_error = 1; + } + return h; +} +#endif /*__MINGW32__*/ + +/* We do only support dlopen and the Windows emulation of it. */ +#ifndef HAVE_DL_DLOPEN +#undef USE_DYNAMIC_LINKING +#endif + + +static void * +load_module (const char *name) +{ +#ifdef USE_DYNAMIC_LINKING + const char *err; + void *handle; + void *sym; + +#ifndef __MINGW32__ + /* Make sure we are not setuid. */ + if (getuid() != geteuid()) + log_bug("trying to load an extension while still setuid\n"); +#endif + + handle = dlopen (name, RTLD_NOW); + if (!name) + { + /*log_error ("error loading module `%s': %s\n", name, dlerror());*/ + goto failure; + } + + sym = dlsym (handle, "idea_get_info"); + if (dlerror ()) + sym = dlsym (handle, "_idea_get_info"); + if ((err=dlerror())) + { + log_info ("invalid module `%s': %s\n", name, err); + goto failure; + } + + return sym; + + failure: + if (handle) + dlclose (handle); +#endif /*USE_DYNAMIC_LINKING*/ + return NULL; +} + + +const char * +idea_get_info( int algo, size_t *keylen, + size_t *blocksize, size_t *contextsize, + int (**r_setkey)( void *c, byte *key, unsigned keylen ), + void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ), + void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf ) + ) +{ + static int initialized; + static const char * (*info_fnc)(int, size_t*, size_t*, size_t*, + int (**)( void *, byte *, unsigned), + void (**)( void *, byte *, byte *), + void (**)( void *, byte *, byte *)); + const char *rstr; + int i; + + if (!initialized) + { + initialized = 1; + for (i=0; (rstr = dynload_enum_module_names (i)); i++) + { + info_fnc = load_module (rstr); + if (info_fnc) + break; + } + } + if (!info_fnc) + return NULL; /* dynloadable module not found. */ + rstr = info_fnc (algo, keylen, blocksize, contextsize, + r_setkey, r_encrypt, r_decrypt); + if (rstr && *keylen == 128 && *blocksize == 8 + && *r_setkey && *r_encrypt && r_decrypt) + return rstr; + return NULL; +} + diff --git a/cipher/md.c b/cipher/md.c index 49728638b..85c1f5b2a 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -1,5 +1,5 @@ /* md.c - message digest dispatcher - * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -27,9 +27,7 @@ #include "util.h" #include "cipher.h" #include "errors.h" -#include "dynload.h" -#include "rmd.h" - +#include "algorithms.h" /**************** * This structure is used for the list of available algorithms @@ -54,97 +52,63 @@ static struct md_digest_list_s *digest_list; static struct md_digest_list_s * -new_list_item( int algo, +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*)) ) + void (**)(void*),byte *(**)(void*))) { - struct md_digest_list_s *r; + 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; + 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; + if (r) + { + r->next = digest_list; + digest_list = r; + } + return r; } -/**************** - * Try to load the modules with the requeste algorithm - * and return true if new modules are available - * If req_alog is -1 try to load all digest algorithms. +/* + Load all available hash algorithms and return true. Subsequent + calls will return 0. */ static int -load_digest_module( int req_algo ) +load_digest_module (void) { - static int initialized = 0; - static u32 checked_algos[256/32]; - static int checked_all = 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*)); + static int initialized = 0; - if( !initialized ) { - cipher_modules_constructor(); - initialized = 1; - } - algo = req_algo; - if( algo > 255 || !algo ) - return 0; /* algorithm number too high (does not fit into out bitmap)*/ - if( checked_all ) - return 0; /* already called with -1 */ - if( algo < 0 ) - checked_all = 1; - else if( (checked_algos[algo/32] & (1 << (algo%32))) ) - return 0; /* already checked and not found */ - else - checked_algos[algo/32] |= (1 << (algo%32)); + if (initialized) + return 0; + initialized = 1; - while( enum_gnupgext_digests( &context, &algo, &get_info ) ) { - if( req_algo != -1 && algo != req_algo ) - continue; - 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; - if( req_algo != -1 ) - break; - } - enum_gnupgext_digests( &context, NULL, NULL ); - return any; -} + /* We load them in reverse order so that the most + frequently used are the first in the list. */ + new_list_item (DIGEST_ALGO_TIGER, tiger_get_info); + if (!new_list_item (DIGEST_ALGO_MD5, md5_get_info)) + BUG (); + if (!new_list_item (DIGEST_ALGO_RMD160, rmd160_get_info)) + BUG (); + if (!new_list_item (DIGEST_ALGO_SHA1, sha1_get_info)) + BUG (); + return 1; +} /**************** - * Map a string to the digest algo - */ + * Map a string to the digest algo */ int string_to_digest_algo( const char *string ) { @@ -154,7 +118,7 @@ string_to_digest_algo( const char *string ) for(r = digest_list; r; r = r->next ) if( !ascii_strcasecmp( r->name, string ) ) return r->algo; - } while( !r && load_digest_module(-1) ); + } while( !r && load_digest_module () ); return 0; } @@ -171,7 +135,7 @@ digest_algo_to_string( int algo ) for(r = digest_list; r; r = r->next ) if( r->algo == algo ) return r->name; - } while( !r && load_digest_module( algo ) ); + } while( !r && load_digest_module () ); return NULL; } @@ -185,7 +149,7 @@ check_digest_algo( int algo ) for(r = digest_list; r; r = r->next ) if( r->algo == algo ) return 0; - } while( !r && load_digest_module(algo) ); + } while( !r && load_digest_module () ); return G10ERR_DIGEST_ALGO; } @@ -232,7 +196,7 @@ md_enable( MD_HANDLE h, int algo ) for(r = digest_list; r; r = r->next ) if( r->algo == algo ) break; - } while( !r && load_digest_module( algo ) ); + } while( !r && load_digest_module () ); if( !r ) { log_error("md_enable: algorithm %d not available\n", algo ); return; @@ -457,7 +421,7 @@ md_digest_length( int algo ) if( r->algo == algo ) return r->mdlen; } - } while( !r && load_digest_module( algo ) ); + } while( !r && load_digest_module () ); log_error("WARNING: no length for md algo %d\n", algo); return 0; } @@ -480,7 +444,7 @@ md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ) return r->asnoid; } } - } while( !r && load_digest_module( algo ) ); + } while( !r && load_digest_module () ); log_bug("no asn for md algo %d\n", algo); return NULL; } @@ -512,13 +476,13 @@ md_stop_debug( MD_HANDLE md ) fclose(md->debug); md->debug = NULL; } - #ifdef HAVE_U64_TYPEDEF +#ifdef HAVE_U64_TYPEDEF { /* a kludge to pull in the __muldi3 for Solaris */ volatile u32 a = (u32)(ulong)md; volatile u64 b = 42; volatile u64 c; c = a * b; } - #endif +#endif } diff --git a/cipher/md5.c b/cipher/md5.c index ef6886eb4..ca605b6fd 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -36,7 +36,7 @@ #include #include "util.h" #include "memory.h" -#include "dynload.h" +#include "algorithms.h" #include "bithelp.h" @@ -337,7 +337,7 @@ md5_read( MD5_CONTEXT *hd ) * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. */ -static const char * +const char * md5_get_info( int algo, size_t *contextsize, byte **r_asnoid, int *r_asnlen, int *r_mdlen, void (**r_init)( void *c ), @@ -365,63 +365,3 @@ md5_get_info( int algo, size_t *contextsize, return "MD5"; } - -#ifndef IS_MODULE -static -#endif -const char * const gnupgext_version = "MD5 ($Revision$)"; - -static struct { - int class; - int version; - int value; - void (*func)(void); -} func_table[] = { - { 10, 1, 0, (void(*)(void))md5_get_info }, - { 11, 1, 1 }, -}; - - -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if( i >= DIM(func_table) || i < 0 ) - 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; -#ifndef __riscos__ - default: ret = func_table[i].func; break; -#else /* __riscos__ */ - default: ret = (void *) func_table[i].func; break; -#endif /* __riscos__ */ - } - i++; - } while( what && what != *class ); - - *sequence = i; - return ret; -} - - - - -#ifndef IS_MODULE -void -md5_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); -} -#endif - - - -/* end of file */ diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 9136fa544..853c518be 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -31,8 +31,6 @@ #include "elgamal.h" #include "dsa.h" #include "rsa.h" -#include "dynload.h" - #define TABLE_SIZE 10 @@ -58,6 +56,7 @@ static struct pubkey_table_s pubkey_table[TABLE_SIZE]; static int disabled_algos[TABLE_SIZE]; +#if 0 static int dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) { log_bug("no generate() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } @@ -65,6 +64,7 @@ dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) static int dummy_check_secret_key( int algo, MPI *skey ) { log_bug("no check_secret_key() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } +#endif static int dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) @@ -83,10 +83,11 @@ dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey, int (*cmp)(void *, MPI), void *opaquev ) { log_bug("no verify() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } +#if 0 static unsigned dummy_get_nbits( int algo, MPI *pkey ) { log_bug("no get_nbits() for %d\n", algo ); return 0; } - +#endif /**************** * Put the static entries into the table. @@ -215,73 +216,13 @@ static int load_pubkey_modules(void) { static int initialized = 0; - static int done = 0; - void *context = NULL; - struct pubkey_table_s *ct; - int ct_idx; - int i; - const char *name; - int any = 0; - if( !initialized ) { - cipher_modules_constructor(); setup_pubkey_table(); initialized = 1; return 1; } - if( done ) - return 0; - done = 1; - for(ct_idx=0, ct = pubkey_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) { - if( !ct->name ) - break; - } - if( ct_idx >= TABLE_SIZE-1 ) - BUG(); /* table already full */ - /* now load all extensions */ - while( (name = enum_gnupgext_pubkeys( &context, &ct->algo, - &ct->npkey, &ct->nskey, &ct->nenc, - &ct->nsig, &ct->use, - &ct->generate, - &ct->check_secret_key, - &ct->encrypt, - &ct->decrypt, - &ct->sign, - &ct->verify, - &ct->get_nbits )) ) { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == ct->algo ) - break; - if( pubkey_table[i].name ) { - log_info("skipping pubkey %d: already loaded\n", ct->algo ); - continue; - } - - if( !ct->generate ) ct->generate = dummy_generate; - if( !ct->check_secret_key ) ct->check_secret_key = - dummy_check_secret_key; - if( !ct->encrypt ) ct->encrypt = dummy_encrypt; - if( !ct->decrypt ) ct->decrypt = dummy_decrypt; - if( !ct->sign ) ct->sign = dummy_sign; - if( !ct->verify ) ct->verify = dummy_verify; - if( !ct->get_nbits ) ct->get_nbits= dummy_get_nbits; - /* put it into the table */ - if( g10_opt_verbose > 1 ) - log_info("loaded pubkey %d (%s)\n", ct->algo, name); - ct->name = name; - ct_idx++; - ct++; - any = 1; - /* check whether there are more available table slots */ - if( ct_idx >= TABLE_SIZE-1 ) { - log_info("pubkey table full; ignoring other extensions\n"); - break; - } - } - enum_gnupgext_pubkeys( &context, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL ); - return any; + return 0; } diff --git a/cipher/rand-internal.h b/cipher/rand-internal.h index 6f5b52bae..eb81174f8 100644 --- a/cipher/rand-internal.h +++ b/cipher/rand-internal.h @@ -20,12 +20,16 @@ #ifndef G10_RAND_INTERNAL_H #define G10_RAND_INTERNAL_H -void rndlinux_constructor(void); -void rndunix_constructor(void); -void rndw32_constructor(void); -void rndos2_constructor(void); -void rndatari_constructor(void); -void rndmvs_constructor(void); -void rndriscos_constructor(void); +int rndunix_gather_random (void (*add)(const void*, size_t, int), + int requester, size_t length, int level); +int rndlinux_gather_random (void (*add)(const void*, size_t, int), + int requester, size_t length, int level); +int rndegd_gather_random (void (*add)(const void*, size_t, int), + int requester, size_t length, int level ); +int rndw32_gather_random (void (*add)(const void*, size_t, int), + int requester, size_t length, int level); +int rndw32_gather_random_fast (void (*add)(const void*, size_t, int), + int requester ); + #endif /*G10_RAND_INTERNAL_H*/ diff --git a/cipher/random.c b/cipher/random.c index 2c958d9d4..1d7bf8a93 100644 --- a/cipher/random.c +++ b/cipher/random.c @@ -1,5 +1,5 @@ /* random.c - random number generator - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -56,8 +56,7 @@ #include "i18n.h" #include "random.h" #include "rand-internal.h" -#include "dynload.h" - +#include "algorithms.h" #ifndef RAND_MAX /* for SunOS */ #define RAND_MAX 32767 @@ -125,6 +124,37 @@ static struct { ulong naddbytes; } rndstats; + +static int (* +getfnc_gather_random (void))(void (*)(const void*, size_t, int), int, + size_t, int) +{ +#ifdef USE_RNDLINUX + return rndlinux_gather_random; +#endif +#ifdef USE_RNDUNIX + return rndunix_gather_random; +#endif +#ifdef USE_RNDEGD + return rndegd_gather_random; +#endif +#ifdef USE_RNDW32 + return rndw32_gather_random; +#endif + return NULL; +} + +static void (* +getfnc_fast_random_poll (void))( void (*)(const void*, size_t, int), int) +{ +#ifdef USE_RNDW32 + return rndw32_gather_random_fast; +#endif + return NULL; +} + + + static void initialize(void) { @@ -136,7 +166,6 @@ initialize(void) keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) : m_alloc_clear(POOLSIZE+BLOCKLEN); is_initialized = 1; - cipher_modules_constructor(); } static void @@ -560,7 +589,7 @@ fast_random_poll() if( !is_initialized ) initialize(); initialized = 1; - fnc = dynload_getfnc_fast_random_poll(); + fnc = getfnc_fast_random_poll(); } if( fnc ) { (*fnc)( add_randomness, 1 ); @@ -637,7 +666,7 @@ read_random_source( int requester, size_t length, int level ) if( !fnc ) { if( !is_initialized ) initialize(); - fnc = dynload_getfnc_gather_random(); + fnc = getfnc_gather_random(); if( !fnc ) { faked_rng = 1; fnc = gather_faked; @@ -685,3 +714,4 @@ gather_faked( void (*add)(const void*, size_t, int), int requester, return 0; /* okay */ } + diff --git a/cipher/rmd160.c b/cipher/rmd160.c index e35647af6..54dec6a15 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -26,8 +26,8 @@ #include "util.h" #include "memory.h" #include "rmd.h" -#include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */ -#include "dynload.h" +#include "cipher.h" /* for rmd160_hash_buffer */ +#include "algorithms.h" #include "bithelp.h" @@ -558,7 +558,7 @@ rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ) * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. */ -static const char * +const char * rmd160_get_info( int algo, size_t *contextsize, byte **r_asnoid, int *r_asnlen, int *r_mdlen, void (**r_init)( void *c ), @@ -586,67 +586,3 @@ rmd160_get_info( int algo, size_t *contextsize, return "RIPEMD160"; } - -#ifndef IS_MODULE -static -#endif -const char * const gnupgext_version = "RMD160 ($Revision$)"; - -static struct { - int class; - int version; - int value; - void (*func)(void); -} func_table[] = { - { 10, 1, 0, (void(*)(void))rmd160_get_info }, - { 11, 1, 3 }, -}; - - -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if( i >= DIM(func_table) || i < 0 ) { - 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: -#ifndef __riscos__ - ret = func_table[i].func; -#else /* __riscos__ */ - ret = (void *) func_table[i].func; -#endif /* __riscos__ */ - break; - } - i++; - } while( what && what != *class ); - - *sequence = i; - return ret; -} - - - - -#ifndef IS_MODULE -void -rmd160_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); -} -#endif - diff --git a/cipher/rndegd.c b/cipher/rndegd.c index 64226eabb..7503ab464 100644 --- a/cipher/rndegd.c +++ b/cipher/rndegd.c @@ -1,5 +1,5 @@ /* rndegd.c - interface to the EGD - * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -19,6 +19,9 @@ */ #include + +#ifdef USE_RNDEG + #include #include #include @@ -33,14 +36,10 @@ #include "types.h" #include "util.h" #include "ttyio.h" -#include "dynload.h" +#include "algorithms.h" #include "cipher.h" +#include "i18n.h" -#ifdef IS_MODULE - #define _(a) (a) -#else - #include "i18n.h" -#endif #ifndef offsetof #define offsetof(type, member) ((size_t) &((type *)0)->member) @@ -76,6 +75,11 @@ do_read( int fd, void *buf, size_t nbytes ) } while( n == -1 && errno == EINTR ); if( n == -1 ) return -1; + else if( n == 0 ) { + /* EGD probably died. */ + errno = ECONNRESET; + return -1; + } nread += n; } while( nread < nbytes ); return nbytes; @@ -91,8 +95,8 @@ do_read( int fd, void *buf, size_t nbytes ) * Using a level of 0 should never block and better add nothing * to the pool. So this is just a dummy for EGD. */ -static int -gather_random( void (*add)(const void*, size_t, int), int requester, +int +rndegd_gather_random( void (*add)(const void*, size_t, int), int requester, size_t length, int level ) { static int fd = -1; @@ -175,11 +179,7 @@ gather_random( void (*add)(const void*, size_t, int), int requester, } if( length ) { - #ifdef IS_MODULE - fprintf( stderr, - #else tty_printf( - #endif _("Please wait, entropy is being gathered. Do some work if it would\n" "keep you from getting bored, because it will improve the quality\n" "of the entropy.\n") ); @@ -205,51 +205,4 @@ gather_random( void (*add)(const void*, size_t, int), int requester, return 0; /* success */ } - - -#ifndef IS_MODULE -static -#endif -const char * const gnupgext_version = "RNDEGD ($Revision$)"; - -static struct { - int class; - int version; - int (*func)(void); -} func_table[] = { - { 40, 1, (int (*)(void))gather_random }, -}; - - -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if ( i >= DIM(func_table) || i < 0 ) { - return NULL; - } - *class = func_table[i].class; - *vers = func_table[i].version; - ret = func_table[i].func; - i++; - } while ( what && what != *class ); - - *sequence = i; - return ret; -} - -#ifndef IS_MODULE -void -rndegd_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, - gnupgext_enum_func ); -} -#endif - +#endif /*USE_RNDEGD*/ diff --git a/cipher/rndlinux.c b/cipher/rndlinux.c index 0b138fcda..c31b7f71c 100644 --- a/cipher/rndlinux.c +++ b/cipher/rndlinux.c @@ -20,6 +20,9 @@ #include + +#ifdef USE_RNDLINUX + #include #include #include @@ -41,17 +44,12 @@ #include "types.h" #include "util.h" #include "ttyio.h" -#include "dynload.h" +#include "algorithms.h" -#ifdef IS_MODULE - #define _(a) (a) -#else - #include "i18n.h" -#endif +#include "i18n.h" static int open_device( const char *name, int minor ); -static int gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ); + #if 0 #ifdef HAVE_DEV_RANDOM_IOCTL @@ -92,8 +90,8 @@ open_device( const char *name, int minor ) * Note: Using a level of 0 should never block and better add nothing * to the pool. This is easy to accomplish with /dev/urandom. */ -static int -gather_random( void (*add)(const void*, size_t, int), int requester, +int +rndlinux_gather_random( void (*add)(const void*, size_t, int), int requester, size_t length, int level ) { static int fd_urandom = -1; @@ -132,11 +130,7 @@ gather_random( void (*add)(const void*, size_t, int), int requester, tv.tv_usec = 0; if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) { if( !warn ) - #ifdef IS_MODULE - fprintf(stderr, - #else tty_printf( - #endif _("\n" "Not enough random bytes available. Please do some other work to give\n" "the OS a chance to collect more entropy! (Need %d more bytes)\n"), (int)length ); @@ -144,11 +138,7 @@ _("\n" continue; } else if( rc == -1 ) { - #ifdef IS_MODULE - fprintf(stderr, - #else tty_printf( - #endif "select() error: %s\n", strerror(errno)); continue; } @@ -171,70 +161,4 @@ _("\n" return 0; /* success */ } - - -#ifndef IS_MODULE -static -#endif -const char * const gnupgext_version = "RNDLINUX ($Revision$)"; - -static struct { - int class; - int version; - int (*func)(void); -} func_table[] = { - { 40, 1, (int (*)(void))gather_random }, -}; - - - -/**************** - * 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 - * 40 = get gather_random function - * 41 = get fast_random_poll function - * version = interface version of the function/pointer - * (currently this is 1 for all functions) - */ - -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if ( i >= DIM(func_table) || i < 0 ) { - return NULL; - } - *class = func_table[i].class; - *vers = func_table[i].version; - ret = func_table[i].func; - i++; - } while ( what && what != *class ); - - *sequence = i; - return ret; -} - -#ifndef IS_MODULE -void -rndlinux_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, - gnupgext_enum_func ); -} -#endif - +#endif /*USE_RNDLINUX*/ diff --git a/cipher/rndunix.c b/cipher/rndunix.c index a46b5ec97..c8d140efe 100644 --- a/cipher/rndunix.c +++ b/cipher/rndunix.c @@ -48,6 +48,9 @@ /* General includes */ #include + +#ifdef USE_RNDUNIX + #include #include #include @@ -768,9 +771,9 @@ read_a_msg( int fd, GATHER_MSG *msg ) * Using a level of 0 should never block and better add nothing * to the pool. So this is just a dummy for this gatherer. */ -static int -gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) +int +rndunix_gather_random( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ) { static pid_t gatherer_pid = 0; static int pipedes[2]; @@ -846,70 +849,4 @@ gather_random( void (*add)(const void*, size_t, int), int requester, return 0; } - - -#ifndef IS_MODULE -static -#endif -const char * const gnupgext_version = "RNDUNIX ($Revision$)"; - - -static struct { - int class; - int version; - int (*func)(void); -} func_table[] = { - { 40, 1, (int (*)(void))gather_random }, -}; - -/**************** - * 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 - * 40 = get read_random_source() function - * 41 = get fast_random_poll function - * version = interface version of the function/pointer - * (currently this is 1 for all functions) - */ - -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if ( i >= DIM(func_table) || i < 0 ) { - return NULL; - } - *class = func_table[i].class; - *vers = func_table[i].version; - ret = func_table[i].func; - i++; - } while ( what && what != *class ); - - *sequence = i; - return ret; -} - -#ifndef IS_MODULE -void -rndunix_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, - gnupgext_enum_func ); -} -#endif - - +#endif /*USE_RNDUNIX*/ diff --git a/cipher/rndw32.c b/cipher/rndw32.c index f58d45866..87aa20878 100644 --- a/cipher/rndw32.c +++ b/cipher/rndw32.c @@ -1,5 +1,5 @@ /* rndw32.c - W32 entropy gatherer - * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-1999 * * This file is part of GnuPG. @@ -60,6 +60,9 @@ */ #include + +#ifdef USE_RNDW32 + #include #include #include @@ -74,230 +77,13 @@ #include "types.h" #include "util.h" -#include "dynload.h" +#include "algorithms.h" -/* We do not use the netropy DLL anymore because a standalone program is - * easier to maintain and */ -/*#define USE_ENTROPY_DLL*/ - - - -#ifdef IS_MODULE - #define _(a) (a) -#else - #include "i18n.h" -#endif +#include "i18n.h" static int debug_me; -#ifdef USE_ENTROPY_DLL - -#define WIN32_SLOW_SEEDER 0 -#define WIN32_FAST_SEEDER 1 - -#define PCP_SUCCESS 0 -#define PCP_NULL_POINTER 1 -#define PCP_SEEDER_FAILED 2 -#define PCP_SEEDER_NO_MEM 3 -#define PCP_SEEDER_TOO_SMALL 4 -#define PCP_DLL_LOAD_FAILED 5 -#define PCP_UNKNOWN_PLATFORM 6 -#define PCP_ERROR_VERSION 7 -#define PCP_DLL_FUNC 8 -#define PCP_UNKNOWN_SEEDER_TYPE 9 - - -/**************** - * We sometimes get a SEEDER_TOO_SMALL error, in which case we increment - * the internal buffer by SEEDER_INC_CHUNK until we reach MAX_SEEDER_SIZE - * MAX_SEEDER_SIZE is used as an arbitrary limit to protect against - * bugs in Winseed. - */ -#define MAX_SEEDER_SIZE 500000 -#define SEEDER_INC_CHUNK 50000 - - -typedef void *WIN32_SEEDER; - -static WIN32_SEEDER (WINAPI *create_instance)( byte type, unsigned int *reason); -static void (WINAPI *delete_instance)( WIN32_SEEDER that ); -static unsigned int (WINAPI *get_internal_seed_size)( WIN32_SEEDER that ); -static void (WINAPI *set_internal_seed_size)( WIN32_SEEDER that, - unsigned int new_size); -static unsigned int (WINAPI *get_expected_seed_size)( WIN32_SEEDER that); -static unsigned int (WINAPI *get_seed)( WIN32_SEEDER that, byte *buffer, - unsigned int *desired_length); - -static WIN32_SEEDER slow_seeder, fast_seeder; -static byte *entropy_buffer; -static size_t entropy_buffer_size; - -/**************** - * Load and initialize the winseed DLL - * NOTE: winseed is not part of the GnuPG distribution. It should be available - * at the GNU crypto FTP server site. - * We do not load the DLL on demand to have a better control over the - * location of the library. - */ -static void -load_and_init_winseed( void ) -{ - HANDLE hInstance; - void *addr; - unsigned int reason = 0; - unsigned int n1, n2; - const char *dllname; - - dllname = read_w32_registry_string( "HKEY_LOCAL_MACHINE", - "Software\\GNU\\GnuPG", - "EntropyDLL" ); - if( !dllname ) - dllname = "c:/gnupg/entropy.dll"; - - hInstance = LoadLibrary( dllname ); - if( !hInstance ) - goto failure; - if( !(addr = GetProcAddress( hInstance, "WS_create_instance" )) ) - goto failure; - create_instance = addr; - if( !(addr = GetProcAddress( hInstance, "WS_delete_instance" )) ) - goto failure; - delete_instance = addr; - if( !(addr = GetProcAddress( hInstance, "WS_get_internal_seed_size" )) ) - goto failure; - get_internal_seed_size = addr; - if( !(addr = GetProcAddress( hInstance, "WS_set_internal_seed_size" )) ) - goto failure; - set_internal_seed_size = addr; - if( !(addr = GetProcAddress( hInstance, "WS_get_expected_seed_size" )) ) - goto failure; - get_expected_seed_size = addr; - if( !(addr = GetProcAddress( hInstance, "WS_get_seed" )) ) - goto failure; - get_seed = addr; - - /* we have all the functions - init the system */ - slow_seeder = create_instance( WIN32_SLOW_SEEDER, &reason); - if( !slow_seeder ) { - g10_log_fatal("error creating winseed slow seeder: rc=%u\n", reason ); - goto failure; - } - fast_seeder = create_instance( WIN32_FAST_SEEDER, &reason); - if( !fast_seeder ) { - g10_log_fatal("error creating winseed fast seeder: rc=%u\n", reason ); - goto failure; - } - n1 = get_internal_seed_size( slow_seeder ); - /*g10_log_info("slow buffer size=%u\n", n1);*/ - n2 = get_internal_seed_size( fast_seeder ); - /*g10_log_info("fast buffer size=%u\n", n2);*/ - - entropy_buffer_size = n1 > n2? n1: n2; - entropy_buffer = m_alloc( entropy_buffer_size ); - /*g10_log_info("using a buffer of size=%u\n", entropy_buffer_size );*/ - - return; - - failure: - g10_log_fatal("error loading winseed DLL `%s'\n", dllname ); -} - - - - - -/* Note: we always use the highest level. - * TO boost the performance we may want to add some - * additional code for level 1 - */ -static int -gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - unsigned int result; - unsigned int nbytes; - - if( !level ) - return 0; - - if( !slow_seeder ) - load_and_init_winseed(); - - /* Our estimation on how much entropy we should use is very vague. - * Winseed delivers some amount of entropy on each slow poll and - * we add it to our random pool. Depending on the required quality - * level we adjust the requested length so that for higher quality - * we make sure to add more entropy to our pool. However, as we don't - * like to waste any entropy collected by winseed, we always add - * at least everything we got from winseed. - */ - if( level > 1 ) - length *= 100; - else if( level > 0 ) - length *= 10; - - for(;;) { - nbytes = entropy_buffer_size; - result = get_seed( slow_seeder, entropy_buffer, &nbytes); - if( result == PCP_SEEDER_TOO_SMALL ) { - unsigned int n1 = get_internal_seed_size( slow_seeder ); - - if( n1 > MAX_SEEDER_SIZE ) { - g10_log_fatal("rndw32: internal seeder problem (size=%u)\n", - n1); - return -1; /* actually never reached */ - } - n1 += SEEDER_INC_CHUNK; - set_internal_seed_size( slow_seeder, n1 ); - if( n1 > entropy_buffer_size ) { - entropy_buffer_size = n1; - entropy_buffer = m_realloc( entropy_buffer, - entropy_buffer_size ); - } - continue; - } - - - if( result ) { - g10_log_fatal("rndw32: get_seed(slow) failed: rc=%u\n", result); - return -1; /* actually never reached */ - } - /*g10_log_info("rndw32: slow poll level %d, need %u, got %u\n", - level, (unsigned int)length, (unsigned int)nbytes );*/ - (*add)( entropy_buffer, nbytes, requester ); - if( length <= nbytes ) - return 0; /* okay */ - length -= nbytes; - } -} - -static int -gather_random_fast( void (*add)(const void*, size_t, int), int requester ) -{ - unsigned int result; - unsigned int nbytes; - - if( !fast_seeder ) - load_and_init_winseed(); - - /* winseed delivers a constant ammount of entropy for a fast - * poll. We can simply use this and add it to the pool; no need - * a loop like it is used in the slow poll */ - nbytes = entropy_buffer_size; - result = get_seed( fast_seeder, entropy_buffer, &nbytes); - if( result ) { - g10_log_fatal("rndw32: get_seed(fast) failed: rc=%u\n", result); - return -1; /* actually never reached */ - } - /*g10_log_info("rndw32: fast poll got %u\n", (unsigned int)nbytes );*/ - (*add)( entropy_buffer, nbytes, requester ); - return 0; -} - -#else /* !USE_ENTROPY_DLL */ -/* This is the new code which does not require the entropy.dll */ - /* * Definitions which are missing from the current GNU Windows32Api */ @@ -731,9 +517,9 @@ slow_gatherer_windowsNT( void (*add)(const void*, size_t, int), int requester ) } -static int -gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) +int +rndw32_gather_random (void (*add)(const void*, size_t, int), int requester, + size_t length, int level ) { static int is_initialized; static int is_windowsNT, has_toolhelp; @@ -783,8 +569,8 @@ gather_random( void (*add)(const void*, size_t, int), int requester, -static int -gather_random_fast( void (*add)(const void*, size_t, int), int requester ) +int +rndw32_gather_random_fast( void (*add)(const void*, size_t, int), int requester ) { static int addedFixedItems = 0; @@ -915,58 +701,4 @@ gather_random_fast( void (*add)(const void*, size_t, int), int requester ) } - - - -#endif /* !USE_ENTROPY_DLL */ - - -#ifndef IS_MODULE -static -#endif -const char * const gnupgext_version = "RNDW32 ($Revision$)"; - -static struct { - int class; - int version; - void *func; -} func_table[] = { - { 40, 1, gather_random }, - { 41, 1, gather_random_fast }, -}; - - -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - debug_me = !!getenv("DEBUG_RNDW32"); - - do { - if ( i >= DIM(func_table) || i < 0 ) { - return NULL; - } - *class = func_table[i].class; - *vers = func_table[i].version; - ret = func_table[i].func; - i++; - } while ( what && what != *class ); - - *sequence = i; - return ret; -} - -#ifndef IS_MODULE -void -rndw32_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, - gnupgext_enum_func ); -} -#endif - +#endif /*USE_RNDW32*/ diff --git a/cipher/sha1.c b/cipher/sha1.c index 77749e4ee..06ca2532b 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -38,7 +38,7 @@ #include #include "util.h" #include "memory.h" -#include "dynload.h" +#include "algorithms.h" #include "bithelp.h" @@ -331,7 +331,7 @@ sha1_read( SHA1_CONTEXT *hd ) * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. */ -static const char * +const char * sha1_get_info( int algo, size_t *contextsize, byte **r_asnoid, int *r_asnlen, int *r_mdlen, void (**r_init)( void *c ), @@ -357,69 +357,3 @@ sha1_get_info( int algo, size_t *contextsize, return "SHA1"; } - - - -#ifndef IS_MODULE -static -#endif -const char * const gnupgext_version = "SHA1 ($Revision$)"; - -static struct { - int class; - int version; - int value; - void (*func)(void); -} func_table[] = { - { 10, 1, 0, (void(*)(void))sha1_get_info }, - { 11, 1, 2 }, -}; - - -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if( i >= DIM(func_table) || i < 0 ) { - 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: -#ifndef __riscos__ - ret = func_table[i].func; -#else /* __riscos__ */ - ret = (void *) func_table[i].func; -#endif /* __riscos__ */ - break; - } - i++; - } while( what && what != *class ); - - *sequence = i; - return ret; -} - - - - -#ifndef IS_MODULE -void -sha1_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); -} -#endif - diff --git a/cipher/tiger.c b/cipher/tiger.c index 6da715d48..b5e8a8aad 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -25,7 +25,7 @@ #include #include "util.h" #include "memory.h" - +#include "algorithms.h" #ifdef HAVE_U64_TYPEDEF @@ -879,13 +879,15 @@ tiger_read( TIGER_CONTEXT *hd ) return hd->buf; } +#endif /*HAVE_U64_TYPEDEF*/ + /**************** * 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 * +const char * tiger_get_info( int algo, size_t *contextsize, byte **r_asnoid, int *r_asnlen, int *r_mdlen, void (**r_init)( void *c ), @@ -894,6 +896,7 @@ tiger_get_info( int algo, size_t *contextsize, byte *(**r_read)( void *c ) ) { +#ifdef HAVE_U64_TYPEDEF /* 40: SEQUENCE { * 12: SEQUENCE { * 8: OCTET STRING :54 49 47 45 52 31 39 32 @@ -904,6 +907,7 @@ tiger_get_info( int algo, size_t *contextsize, * * By replacing the 5th byte (0x04) with 0x16 we would have; * 8: IA5String 'TIGER192' + * Fixme: We should use a registered OID. */ static byte asn[18] = { 0x30, 0x28, 0x30, 0x0c, 0x04, 0x08, 0x54, 0x49, 0x47, @@ -922,87 +926,7 @@ tiger_get_info( int algo, size_t *contextsize, *(byte *(**)(TIGER_CONTEXT *))r_read = tiger_read; return "TIGER192"; -} - - - -#ifndef IS_MODULE -static +#else /*!HAVE_U64_TYPEDEF*/ + return NULL; /* Alorithm not available. */ #endif -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) - */ -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - 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; } - - - -#ifndef IS_MODULE -void -tiger_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, - gnupgext_enum_func ); -} -#endif - - -#endif /* HAVE_U64_TYPEDEF */ - diff --git a/configure.ac b/configure.ac index 0918e2782..546859026 100644 --- a/configure.ac +++ b/configure.ac @@ -29,8 +29,6 @@ AC_INIT(gnupg, 1.1.91, bug-gnupg@gnu.org) development_version=yes ALL_LINGUAS="cs da de eo el es et fr gl id it ja nl pl pt_BR pt sv tr" -static_modules="sha1 md5 rmd160" -static_random_module="" PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION @@ -47,18 +45,10 @@ AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package]) AC_DEFINE(_GNU_SOURCE,1,[Some tests rely on this (stpcpy) and it should be used for new programs anyway]) -AC_PROG_AWK - -MODULES_IN_CIPHER=`$AWK '/^EXTRA_PROGRAMS/ { for(i=3;i<=NF;i++) print $i}' \ - $srcdir/cipher/Makefile.am` - dnl dnl Check for random module options dnl -dnl Fixme: get the list of available modules from MODULES_IN_CIPHER -dnl and check against this list - -AC_MSG_CHECKING([which static random module to use]) +AC_MSG_CHECKING([which random module to use]) AC_ARG_ENABLE(static-rnd, [ --enable-static-rnd=[egd|unix|linux|none] ], [use_static_rnd=$enableval], [use_static_rnd=default] ) @@ -68,7 +58,7 @@ if test "$use_static_rnd" = no; then fi case "$use_static_rnd" in - egd | linux | unix | none | default ) + egd | linux | unix | default ) AC_MSG_RESULT($use_static_rnd) ;; * ) @@ -226,21 +216,6 @@ AM_MAINTAINER_MODE dnl Checks for programs. -dnl -dnl Setup some stuff depending on host/target. -dnl -case "${target}" in - *-*-mingw32*) - disallowed_modules="rndunix rndlinux rndegd" - ;; - *-*-cygwin*) - disallowed_modules="rndunix rndlinux rndegd tiger" - ;; - *) - disallowed_modules="rndw32" - ;; -esac - AC_PROG_MAKE_SET AM_SANITY_CHECK missing_dir=`cd $ac_aux_dir && pwd` @@ -334,11 +309,6 @@ esac AC_SUBST(MPI_OPT_FLAGS) GNUPG_SYS_SYMBOL_UNDERSCORE -GNUPG_CHECK_PIC -GNUPG_CHECK_EXPORTDYNAMIC -if test "$NO_PIC" = yes; then - try_dynload=no -fi dnl Must check for network library requirements before doing link tests dnl for ldap, for example. If ldap libs are static (or dynamic and without @@ -443,8 +413,7 @@ AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", # -# 1. Set flags to be used for the extension modules -# 2. Set names of random devices +# 1. Set names of random devices # NAME_OF_DEV_RANDOM="/dev/random" NAME_OF_DEV_URANDOM="/dev/urandom" @@ -452,57 +421,6 @@ case "${target}" in *-openbsd* | *-netbsd*) NAME_OF_DEV_RANDOM="/dev/srandom" NAME_OF_DEV_URANDOM="/dev/urandom" - DYNLINK_MOD_CFLAGS="-shared -rdynamic $CFLAGS_PIC -Wl,-Bshareable -Wl,-x" - ;; - - hpux*) - # if using the vendor (ANSI) compiler, arrange to have `-b' passed - # to the linker. If using gcc, it supports `-shared' to do the same. - if test -n "$GCC" ; then - DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" - else - DYNLINK_MOD_CFLAGS='-Wl,-b' - fi - ;; - - *-irix6.5*) - # Irix 6.5 (and probably a lot earlier, but I only still have - # access to 6.5.x) doesn't require any additional flags, as `-KPIC' - # is the default. Also, `-shared' works with the vendor compiler - DYNLINK_MOD_CFLAGS="-shared" - ;; - - alpha*-dec-osf*) - # osf (i.e. OSF/1, Digital UNIX, or Tru64 UNIX, pick any one...) - # on alpha doesn't require any PIC flags, everything is PIC. - # This may not be the case for osf ports to other machines, so - # hence the more specific match for target. - # - # Also, `-shared' works with the vendor compiler or gcc. - # -expect_unresolved turns off warnings about unresolved symbols. - DYNLINK_MOD_CFLAGS='-shared -Wl,-expect_unresolved,\*' - ;; - - *-solaris*) - # -shared is a gcc-ism. Find pic flags from GNUPG_CHECK_PIC. - if test -n "$GCC" ; then - DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" - else - DYNLINK_MOD_CFLAGS="-G $CFLAGS_PIC" - fi - ;; - - *-irix* | *-dec-osf* ) - DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" - ;; - - *) - # -shared is a gcc-ism. Find pic flags from GNUPG_CHECK_PIC. - if test -n "$GCC" ; then - DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" - else - DYNLINK_MOD_CFLAGS="$CFLAGS_PIC" - fi ;; esac AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM", @@ -515,14 +433,14 @@ AC_SUBST(MPI_OPT_FLAGS) dnl Checks for libraries. if test "$try_gettext" = yes; then -AM_GNU_GETTEXT + AM_GNU_GETTEXT else -USE_NLS=no -USE_INCLUDED_LIBINTL=no -BUILD_INCLUDED_LIBINTL=no -AC_SUBST(USE_NLS) -AC_SUBST(USE_INCLUDED_LIBINTL) -AC_SUBST(BUILD_INCLUDED_LIBINTL) + USE_NLS=no + USE_INCLUDED_LIBINTL=no + BUILD_INCLUDED_LIBINTL=no + AC_SUBST(USE_NLS) + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(BUILD_INCLUDED_LIBINTL) fi @@ -533,49 +451,20 @@ if test "$try_dynload" = yes ; then [define to enable the use of extensions]) AC_DEFINE(HAVE_DL_DLOPEN,1, [Defined when the dlopen function family is available]) - DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" - use_gnupg_extensions=yes else AC_CHECK_FUNCS(dlopen) if test "$ac_cv_func_dlopen" = "yes"; then AC_DEFINE(USE_DYNAMIC_LINKING) AC_DEFINE(HAVE_DL_DLOPEN) - DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" - use_gnupg_extensions=yes - else - AC_CHECK_LIB(dld,shl_load) - if test "$ac_cv_lib_dld_shl_load" = "yes"; then - AC_DEFINE(USE_DYNAMIC_LINKING) - AC_DEFINE(HAVE_DL_SHL_LOAD,1, - [Defined if the shl_load function family is available]) - DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" - use_gnupg_extensions=yes -dnl ----------------- -dnl DLD is not ready for use. So I better disable this test -dnl -dnl AC_CHECK_LIB(dld,dld_link) -dnl if test "$ac_cv_lib_dld_dld_link" = "yes"; then -dnl AC_DEFINE(USE_DYNAMIC_LINKING) -dnl AC_DEFINE(HAVE_DLD_DLD_LINK) -dnl DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" -dnl use_gnupg_extensions=yes -dnl --------------- - fi fi fi else AC_MSG_CHECKING(for dynamic loading) DYNLINK_LDFLAGS= DYNLINK_MOD_CFLAGS= - use_gnupg_extensions=no AC_MSG_RESULT(has been disabled) fi -AM_CONDITIONAL(ENABLE_GNUPG_EXTENSIONS, test "$use_gnupg_extensions" = yes ) -AC_SUBST(DYNLINK_LDFLAGS) -AC_SUBST(DYNLINK_MOD_CFLAGS) - - dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(unistd.h langinfo.h termio.h locale.h) @@ -713,9 +602,9 @@ fi dnl -dnl Figure out the default linkage mode for random modules +dnl Figure out the default random module. dnl -print_egd_notice=no +static_random_module="" if test "$use_static_rnd" = default; then if test "$ac_cv_have_dev_random" = yes; then static_random_module="rndlinux" @@ -723,9 +612,6 @@ if test "$use_static_rnd" = default; then case "${target}" in *-*-mingw32*|*-*-cygwin*) static_random_module="rndw32" - AC_DEFINE(USE_STATIC_RNDW32,1, - [At some point in the code we need to know that - we use the Windows random module.]) ;; i?86-emx-os2|i?86-*-os2*emx) static_random_module="rndos2" @@ -738,24 +624,19 @@ if test "$use_static_rnd" = default; then ;; *) static_random_module="rndunix" - print_egd_notice=yes ;; esac fi -else - if test "$use_static_rnd" = none; then - : - else - static_random_module="rnd$use_static_rnd" - if test "$use_static_rnd" = "unix"; then - print_egd_notice=yes - fi - fi fi - - -if test "$print_egd_notice" = "yes"; then - AC_MSG_WARN([[ +case "$static_random_module" in + rndlinux) + AC_DEFINE(USE_RNDLINUX,1, + [Defined if the /dev/random based RNG shoudl be used.]) + ;; + rndunix) + AC_DEFINE(USE_RNDUNIX,1, + [Defined if the default Unix RNG should be used.]) + AC_MSG_WARN([[ *** *** The performance of the UNIX random gatherer module is not very good *** and it does not keep the entropy pool over multiple invocations of @@ -769,86 +650,36 @@ if test "$print_egd_notice" = "yes"; then *** *** http://www.gnupg.org/download.html#egd *** -*** You may want to run ./configure with --enable-static-rnd=none to be -*** able to load the EGD client code dynamically; this way you can choose -*** between RNDUNIX and RNDEGD without recompilation. +*** You may want to run ./configure with --enable-static-rnd=egd to use it. ***]]) + ;; + rndegd) + AC_DEFINE(USE_RNDEGD,1, + [Defined if the EGD based RNG shoudl be used.]) + ;; + rndw32) + AC_DEFINE(USE_RNDW32,1, + [Defined if the Windows specific RNG should be used.]) + ;; + *) + AC_MSG_ERROR(no random module available) + ;; +esac + +# We don't need idea but some people claim that they need it for +# research etc., so we allow to place an idea source code into the +# cipher directory and statically link it if available, otherwise we +# link to a stub. We don't use AC_CHECK_FILE to avoid caching. +AC_MSG_CHECKING(for extra cipher modules) +tmp="" +if test -f $srcdir/cipher/idea.c; then + IDEA_O=idea.o + tmp=idea +else + IDEA_O=idea-stub.o fi - -dnl -dnl Parse the modules list and build the list -dnl of static and dynamically linked modules -dnl -dnl (We always need a static rmd160) -static_modules="$static_modules rmd160 $static_random_module" -STATIC_CIPHER_NAMES="" -STATIC_CIPHER_OBJS="" -DYNAMIC_CIPHER_MODS="" -show_dynlink="" -for name in $MODULES_IN_CIPHER; do - x="yes" - for i in $disallowed_modules; do - if test "$name" = "$i" ; then x="no" ; fi - done; - if test $x = yes; then - x="no" - for i in $static_modules; do - if test "$name" = "$i" ; then - x="yes" - fi - done; - if test $x = yes; then - STATIC_CIPHER_NAMES="$STATIC_CIPHER_NAMES $name" - STATIC_CIPHER_OBJS="$STATIC_CIPHER_OBJS $name.o" - else - DYNAMIC_CIPHER_MODS="$DYNAMIC_CIPHER_MODS $name" - show_dynlink="$show_dynlink $name" - fi - fi -done -AC_SUBST(STATIC_CIPHER_OBJS) -AC_SUBST(STATIC_CIPHER_NAMES) -AC_SUBST(DYNAMIC_CIPHER_MODS) - -dnl -dnl And build the constructor file -dnl - -test -d cipher || mkdir cipher -cat <cipher/construct.c -/* automatically generated by configure - do not edit */ - -G10EOF -show_statlink="" -for name in $STATIC_CIPHER_NAMES; do - echo "void ${name}_constructor(void);" >>cipher/construct.c - show_statlink="$show_statlink $name" -done - -cat <>cipher/construct.c - -void -cipher_modules_constructor(void) -{ - static int done = 0; - if( done ) - return; - done = 1; - -G10EOF -for name in $STATIC_CIPHER_NAMES; do - echo " ${name}_constructor();" >>cipher/construct.c -done -echo '}' >>cipher/construct.c - - - - -dnl -dnl Figure how to link the cipher modules -dnl -AC_SUBST(STATIC_CIPHER_OBJS) -AC_SUBST(DYNAMIC_CIPHER_MODS) +AC_SUBST(IDEA_O) +AC_MSG_RESULT($tmp) dnl setup assembler stuff @@ -1032,14 +863,7 @@ AC_OUTPUT # Give some feedback echo echo " Configured for: $PRINTABLE_OS_NAME ($target)" -if test -n "$show_dynlink"; then - echo " Dynamically linked modules:$show_dynlink" -fi -if test -n "$show_statlink"; then - echo " Statically linked modules:$show_statlink" -fi if test -n "$show_extraasm"; then echo " Extra cpu specific functions:$show_extraasm" fi echo - diff --git a/doc/gpg.sgml b/doc/gpg.sgml index 8899121f7..98610b699 100644 --- a/doc/gpg.sgml +++ b/doc/gpg.sgml @@ -1245,7 +1245,8 @@ Using this option will also prevent the creation of a Load an extension module. If &ParmName; does not contain a slash it is searched in "/usr/local/lib/gnupg" -See the manual for more information about extensions. +Extension are in gernal not useful anymore; the use of this +option is deprecated. diff --git a/g10/ChangeLog b/g10/ChangeLog index ec4731877..52357d6c3 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2002-08-02 Werner Koch + + * Makefile.am (LDFLAGS): Removed DYNLINK_LDFLAGS. + 2002-07-30 David Shaw * options.h, g10.c (main), mainproc.c (proc_encrypted): Return a diff --git a/g10/Makefile.am b/g10/Makefile.am index f59cd8b2d..13ac50b6d 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -22,7 +22,7 @@ INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl EXTRA_DIST = options.skel # it seems that we can't use this with automake 1.5 #OMIT_DEPENDENCIES = zlib.h zconf.h -LDFLAGS = @LDFLAGS@ @DYNLINK_LDFLAGS@ +LDFLAGS = @LDFLAGS@ needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a #noinst_PROGRAMS = gpgd diff --git a/include/cipher.h b/include/cipher.h index 634569199..7ad3772ba 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -134,8 +134,8 @@ void md_stop_debug( MD_HANDLE a ); md_write( (h), NULL, 0 ); \ (h)->buffer[(h)->bufcount++] = (c) & 0xff; \ } while(0) -/*-- rmd160.c --*/ -void rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ); + +void rmd160_hash_buffer (char *outbuf, const char *buffer, size_t length); /*-- cipher.c --*/