1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

The big extension module removal.

This commit is contained in:
Werner Koch 2002-08-03 10:50:53 +00:00
parent 14d050a272
commit 85aa3e18c2
28 changed files with 574 additions and 1880 deletions

View file

@ -1,3 +1,41 @@
2002-08-03 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
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 <dshaw@jabberwocky.com>
* random.c: "warning" -> "WARNING"

View file

@ -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

66
cipher/algorithms.h Normal file
View file

@ -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*/

View file

@ -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*/

View file

@ -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;
}

View file

@ -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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_DL_DLOPEN
#include <dlfcn.h>
#elif defined(HAVE_DLD_DLD_LINK)
#include <dld.h>
#elif defined(HAVE_DL_SHL_LOAD)
#include <dl.h>
#include <errno.h>
#endif
#ifdef __MINGW32__
#include <windows.h>
#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;
}

187
cipher/idea-stub.c Normal file
View file

@ -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 <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_DL_DLOPEN
#include <dlfcn.h>
#endif
#ifdef __MINGW32__
#include <windows.h>
#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;
}

View file

@ -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
}

View file

@ -36,7 +36,7 @@
#include <assert.h>
#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 */

View file

@ -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;
}

View file

@ -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*/

View file

@ -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 */
}

View file

@ -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

View file

@ -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 <config.h>
#ifdef USE_RNDEG
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@ -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*/

View file

@ -20,6 +20,9 @@
#include <config.h>
#ifdef USE_RNDLINUX
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@ -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*/

View file

@ -48,6 +48,9 @@
/* General includes */
#include <config.h>
#ifdef USE_RNDUNIX
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -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*/

View file

@ -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 <config.h>
#ifdef USE_RNDW32
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@ -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*/

View file

@ -38,7 +38,7 @@
#include <assert.h>
#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

View file

@ -25,7 +25,7 @@
#include <assert.h>
#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 */