Made Arcfour work
[libgcrypt.git] / cipher / dynload.c
1 /* dynload.c - load cipher extensions
2  *      Copyright (C) 1998, 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #ifdef HAVE_DL_DLOPEN
27   #include <dlfcn.h>
28 #elif defined(HAVE_DLD_DLD_LINK)
29   #include <dld.h>
30 #elif defined(HAVE_DL_SHL_LOAD)
31   #include <dl.h>
32   #include <errno.h>
33 #endif
34 #include "g10lib.h"
35 #include "cipher.h"
36 #include "dynload.h"
37
38 #ifdef WITH_SYMBOL_UNDERSCORE
39   #define SYMBOL_VERSION "_gnupgext_version"
40   #define SYMBOL_ENUM    "_gnupgext_enum_func"
41 #else
42   #define SYMBOL_VERSION "gnupgext_version"
43   #define SYMBOL_ENUM    "gnupgext_enum_func"
44 #endif
45
46
47 #ifndef RTLD_NOW
48   #define RTLD_NOW  1
49 #endif
50
51 #ifdef HAVE_DL_SHL_LOAD  /* HPUX has shl_load instead of dlopen */
52 #define HAVE_DL_DLOPEN
53 #define dlopen(PATHNAME,MODE) \
54     ((void *) shl_load(PATHNAME, DYNAMIC_PATH | \
55               (((MODE) & RTLD_NOW) ? BIND_IMMEDIATE : BIND_DEFERRED), 0L))
56 #define dlclose(HANDLE) shl_unload((shl_t) (HANDLE))
57 #define dlerror() (errno == 0 ? NULL : strerror(errno))
58
59 static void *
60 dlsym(void *handle, char *name)
61 {
62     void *addr;
63     if (shl_findsym((shl_t *)&handle,name,(short)TYPE_UNDEFINED,&addr) != 0) {
64       return NULL;
65     }
66     return addr;
67 }
68 #endif /*HAVE_DL_SHL_LOAD*/
69
70
71
72 typedef struct ext_list {
73     struct ext_list *next;
74     int internal;
75   #ifdef HAVE_DL_DLOPEN
76     void *handle; /* handle from dlopen() */
77   #else
78     int handle;   /* if the function has been loaded, this is true */
79   #endif
80     int  failed;  /* already tried but failed */
81     void * (*enumfunc)(int, int*, int*, int*);
82     char *hintstr; /* pointer into name */
83     char name[1];
84 } *EXTLIST;
85
86 static EXTLIST extensions;
87
88 typedef struct {
89     EXTLIST r;
90     int seq1;
91     int seq2;
92     void *sym;
93     int reqalgo;
94 } ENUMCONTEXT;
95
96
97 #ifdef HAVE_DLD_DLD_LINK
98 static char *mainpgm_path;
99 static int did_dld_init;
100 static int dld_available;
101 #endif
102
103
104 static int
105 cmp_filenames( const char *a, const char *b )
106 {
107     /* ? check whether this is an absolute filename and
108      * resolve symlinks?
109      */
110   #ifdef HAVE_DRIVE_LETTERS
111     return stricmp(a,b);
112   #else
113     return strcmp(a,b);
114   #endif
115 }
116
117
118 /****************
119  * Register an extension module.  The last registered module will
120  * be loaded first.  A name may have a list of classes
121  * appended; e.g:
122  *      mymodule.so(1:17,3:20,3:109)
123  * means that this module provides digest algorithm 17 and public key
124  * algorithms 20 and 109.  This is only a hint but if it is there the
125  * loader may decide to only load a module which claims to have a
126  * requested algorithm.
127  *
128  * mainpgm is the path to the program which wants to load a module
129  * it is only used in some environments.
130  */
131 void
132 _gcry_register_cipher_extension( const char *mainpgm, const char *fname )
133 {
134     EXTLIST r, el, intex;
135     char *p, *pe;
136
137   #ifdef HAVE_DLD_DLD_LINK
138     if( !mainpgm_path && mainpgm && *mainpgm )
139         mainpgm_path = m_strdup(mainpgm);
140   #endif
141     el = gcry_xcalloc( 1, sizeof *el + strlen(fname) );
142     strcpy(el->name, fname );
143
144     /* check whether we have a class hint */
145     if( (p=strchr(el->name,'(')) && (pe=strchr(p+1,')')) && !pe[1] ) {
146         *p = *pe = 0;
147         el->hintstr = p+1;
148     }
149     else
150         el->hintstr = NULL;
151
152     /* check that it is not already registered */
153     intex = NULL;
154     for(r = extensions; r; r = r->next ) {
155         if( !cmp_filenames(r->name, el->name) ) {
156             log_info("extension `%s' already registered\n", el->name );
157             gcry_free(el);
158             return;
159         }
160         else if( r->internal )
161             intex = r;
162     }
163     /* and register */
164     /* we put them after the internal extension modules */
165     /* this is so that the external modules do not get loaded */
166     /* as soon as the internal modules are requested */
167     if( intex ) {
168         el->next = intex->next;
169         intex->next = el;
170     }
171     else {
172         el->next = extensions;
173         extensions = el;
174     }
175 }
176
177 void
178 _gcry_register_internal_cipher_extension(
179                         const char *module_id,
180                         void * (*enumfunc)(int, int*, int*, int*)
181                                   )
182 {
183     EXTLIST r, el;
184
185     el = gcry_xcalloc( 1, sizeof *el + strlen(module_id) );
186     strcpy(el->name, module_id );
187     el->internal = 1;
188
189     /* check that it is not already registered */
190     for(r = extensions; r; r = r->next ) {
191         if( !cmp_filenames(r->name, el->name) ) {
192             log_info("extension `%s' already registered\n", el->name );
193             gcry_free(el);
194             return;
195         }
196     }
197     /* and register */
198     el->enumfunc = enumfunc;
199   #ifdef HAVE_DL_DLOPEN
200     el->handle = (void*)1;
201   #else
202     el->handle = 1;
203   #endif
204     el->next = extensions;
205     extensions = el;
206 }
207
208
209 static int
210 load_extension( EXTLIST el )
211 {
212   #ifdef USE_DYNAMIC_LINKING
213     char **name;
214   #ifdef HAVE_DL_DLOPEN
215     const char *err;
216     int seq = 0;
217     int class, vers;
218     void *sym;
219   #else
220     unsigned long addr;
221     int rc;
222   #endif
223
224     /* make sure we are not setuid */
225     if( getuid() != geteuid() )
226         log_bug("trying to load an extension while still setuid\n");
227
228     /* now that we are not setuid anymore, we can safely load modules */
229   #ifdef HAVE_DL_DLOPEN
230     el->handle = dlopen(el->name, RTLD_NOW);
231     if( !el->handle ) {
232         log_error("%s: error loading extension: %s\n", el->name, dlerror() );
233         goto failure;
234     }
235     name = (char**)dlsym(el->handle, SYMBOL_VERSION);
236     if( (err=dlerror()) ) {
237         log_error("%s: not a gnupg extension: %s\n", el->name, err );
238         goto failure;
239     }
240   #else /* have dld */
241     if( !did_dld_init ) {
242         did_dld_init = 1;
243         if( !mainpgm_path )
244             log_error("DLD is not correctly initialized\n");
245         else {
246             rc = dld_init( dld_find_executable(mainpgm_path) );
247             if( rc )
248                 log_error("DLD init failed: %s\n", dld_strerror(rc) );
249             else
250                 dld_available = 1;
251         }
252     }
253     if( !dld_available ) {
254         log_error("%s: DLD not available\n", el->name );
255         goto failure;
256     }
257
258     rc = dld_link( el->name );
259     if( rc ) {
260         log_error("%s: error loading extension: %s\n",
261                                     el->name, dld_strerror(rc) );
262         goto failure;
263     }
264     addr = dld_get_symbol(SYMBOL_VERSION);
265     if( !addr ) {
266         log_error("%s: not a gnupg extension: %s\n",
267                                 el->name, dld_strerror(dld_errno) );
268         goto failure;
269     }
270     name = (char**)addr;
271   #endif
272
273     if( _gcry_log_verbosity( 2 ) )
274         log_info("%s: %s%s%s%s\n", el->name, *name,
275                   el->hintstr? " (":"",
276                   el->hintstr? el->hintstr:"",
277                   el->hintstr? ")":"");
278
279   #ifdef HAVE_DL_DLOPEN
280     sym = dlsym(el->handle, SYMBOL_ENUM);
281     if( (err=dlerror()) ) {
282         log_error("%s: invalid gnupg extension: %s\n", el->name, err );
283         goto failure;
284     }
285     el->enumfunc = (void *(*)(int,int*,int*,int*))sym;
286   #else /* dld */
287     addr = dld_get_func(SYMBOL_ENUM);
288     if( !addr ) {
289         log_error("%s: invalid gnupg extension: %s\n",
290                                 el->name, dld_strerror(dld_errno) );
291         goto failure;
292     }
293     rc = dld_function_executable_p(SYMBOL_ENUM);
294     if( rc ) {
295         log_error("%s: extension function is not executable: %s\n",
296                                         el->name, dld_strerror(rc) );
297         goto failure;
298     }
299     el->enumfunc = (void *(*)(int,int*,int*,int*))addr;
300     el->handle = 1; /* mark as usable */
301   #endif
302
303   #ifdef HAVE_DL_DLOPEN
304     if( _gcry_log_verbosity( 3 ) ) {
305         /* list the contents of the module */
306         while( (sym = (*el->enumfunc)(0, &seq, &class, &vers)) ) {
307             if( vers != 1 ) {
308                 log_info("%s: ignoring func with version %d\n",el->name,vers);
309                 continue;
310             }
311             switch( class ) {
312               case 11:
313               case 21:
314               case 31:
315                 log_info("%s: provides %s algorithm %d\n", el->name,
316                                 class == 11? "md"     :
317                                 class == 21? "cipher" : "pubkey",
318                                                        *(int*)sym);
319                 break;
320               default:
321                 /*log_debug("%s: skipping class %d\n", el->name, class);*/
322                 break;
323             }
324         }
325     }
326   #endif
327     return 0;
328
329   failure:
330   #ifdef HAVE_DL_DLOPEN
331     if( el->handle ) {
332         dlclose(el->handle);
333         el->handle = NULL;
334     }
335   #endif
336     el->failed = 1;
337   #endif /*USE_DYNAMIC_LINKING*/
338     return -1;
339 }
340
341
342
343 int
344 _gcry_enum_gnupgext_digests( void **enum_context,
345             int *algo,
346             const char *(**r_get_info)( int, size_t*,byte**, int*, int*,
347                                        void (**)(void*),
348                                        void (**)(void*,byte*,size_t),
349                                        void (**)(void*),byte *(**)(void*)) )
350 {
351     EXTLIST r;
352     ENUMCONTEXT *ctx;
353
354     if( !*enum_context ) { /* init context */
355         ctx = gcry_xcalloc( 1, sizeof( *ctx ) );
356         ctx->r = extensions;
357         ctx->reqalgo = *algo;
358         *enum_context = ctx;
359     }
360     else if( !algo ) { /* release the context */
361         gcry_free(*enum_context);
362         *enum_context = NULL;
363         return 0;
364     }
365     else
366         ctx = *enum_context;
367
368     for( r = ctx->r; r; r = r->next )  {
369         int class, vers;
370
371         if( r->failed )
372             continue;
373         if( !r->handle && load_extension(r) )
374             continue;
375         /* get a digest info function */
376         if( ctx->sym )
377             goto inner_loop;
378         while( (ctx->sym = (*r->enumfunc)(10, &ctx->seq1, &class, &vers)) ) {
379             void *sym;
380             /* must check class because enumfunc may be wrong coded */
381             if( vers != 1 || class != 10 )
382                 continue;
383           inner_loop:
384             *r_get_info = ctx->sym;
385             while( (sym = (*r->enumfunc)(11, &ctx->seq2, &class, &vers)) ) {
386                 if( vers != 1 || class != 11 )
387                     continue;
388                 *algo = *(int*)sym;
389                 ctx->r = r;
390                 return 1;
391             }
392             ctx->seq2 = 0;
393         }
394         ctx->seq1 = 0;
395     }
396     ctx->r = r;
397     return 0;
398 }
399
400 const char *
401 _gcry_enum_gnupgext_ciphers( void **enum_context, int *algo,
402                        size_t *keylen, size_t *blocksize, size_t *contextsize,
403                        int  (**setkeyf)( void *c, byte *key, unsigned keylen ),
404                        void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
405                        void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
406                      )
407 {
408     EXTLIST r;
409     ENUMCONTEXT *ctx;
410     const char * (*finfo)(int, size_t*, size_t*, size_t*,
411                           int  (**)( void *, byte *, unsigned),
412                           void (**)( void *, byte *, byte *),
413                           void (**)( void *, byte *, byte *));
414
415     if( !*enum_context ) { /* init context */
416         ctx = gcry_xcalloc( 1, sizeof( *ctx ) );
417         ctx->r = extensions;
418         *enum_context = ctx;
419     }
420     else if( !algo ) { /* release the context */
421         gcry_free(*enum_context);
422         *enum_context = NULL;
423         return NULL;
424     }
425     else
426         ctx = *enum_context;
427
428     for( r = ctx->r; r; r = r->next )  {
429         int class, vers;
430
431         if( r->failed )
432             continue;
433         if( !r->handle && load_extension(r) )
434             continue;
435         /* get a cipher info function */
436         if( ctx->sym )
437             goto inner_loop;
438         while( (ctx->sym = (*r->enumfunc)(20, &ctx->seq1, &class, &vers)) ) {
439             void *sym;
440             /* must check class because enumfunc may be wrong coded */
441             if( vers != 1 || class != 20 )
442                 continue;
443           inner_loop:
444             finfo = ctx->sym;
445             while( (sym = (*r->enumfunc)(21, &ctx->seq2, &class, &vers)) ) {
446                 const char *algname;
447                 if( vers != 1 || class != 21 )
448                     continue;
449                 *algo = *(int*)sym;
450                 algname = (*finfo)( *algo, keylen, blocksize, contextsize,
451                                     setkeyf, encryptf, decryptf );
452                 if( algname ) {
453                     ctx->r = r;
454                     return algname;
455                 }
456             }
457             ctx->seq2 = 0;
458         }
459         ctx->seq1 = 0;
460     }
461     ctx->r = r;
462     return NULL;
463 }
464
465 const char *
466 _gcry_enum_gnupgext_pubkeys( void **enum_context, int *algo,
467     int *npkey, int *nskey, int *nenc, int *nsig, int *use,
468     int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ),
469     int (**check_secret_key)( int algo, MPI *skey ),
470     int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ),
471     int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ),
472     int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ),
473     int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey,
474                     int (*cmp)(void *, MPI), void *opaquev ),
475     unsigned (**get_nbits)( int algo, MPI *pkey ) )
476 {
477     EXTLIST r;
478     ENUMCONTEXT *ctx;
479     const char * (*finfo)( int, int *, int *, int *, int *, int *,
480                            int (**)( int, unsigned, MPI *, MPI **),
481                            int (**)( int, MPI * ),
482                            int (**)( int, MPI *, MPI , MPI * ),
483                            int (**)( int, MPI *, MPI *, MPI * ),
484                            int (**)( int, MPI *, MPI , MPI * ),
485                            int (**)( int, MPI , MPI *, MPI *,
486                                             int (*)(void*,MPI), void *),
487                            unsigned (**)( int , MPI * ) );
488
489     if( !*enum_context ) { /* init context */
490         ctx = gcry_xcalloc( 1, sizeof( *ctx ) );
491         ctx->r = extensions;
492         *enum_context = ctx;
493     }
494     else if( !algo ) { /* release the context */
495         gcry_free(*enum_context);
496         *enum_context = NULL;
497         return NULL;
498     }
499     else
500         ctx = *enum_context;
501
502     for( r = ctx->r; r; r = r->next )  {
503         int class, vers;
504
505         if( r->failed )
506             continue;
507         if( !r->handle && load_extension(r) )
508             continue;
509         /* get a pubkey info function */
510         if( ctx->sym )
511             goto inner_loop;
512         while( (ctx->sym = (*r->enumfunc)(30, &ctx->seq1, &class, &vers)) ) {
513             void *sym;
514             if( vers != 1 || class != 30 )
515                 continue;
516           inner_loop:
517             finfo = ctx->sym;
518             while( (sym = (*r->enumfunc)(31, &ctx->seq2, &class, &vers)) ) {
519                 const char *algname;
520                 if( vers != 1 || class != 31 )
521                     continue;
522                 *algo = *(int*)sym;
523                 algname = (*finfo)( *algo, npkey, nskey, nenc, nsig, use,
524                                     generate, check_secret_key, encryptf,
525                                     decryptf, sign, verify, get_nbits );
526                 if( algname ) {
527                     ctx->r = r;
528                     return algname;
529                 }
530             }
531             ctx->seq2 = 0;
532         }
533         ctx->seq1 = 0;
534     }
535     ctx->r = r;
536     return NULL;
537 }
538
539
540 int (*
541 _gcry_dynload_getfnc_gather_random())(void (*)(const void*, size_t, int), int,
542                                                             size_t, int)
543 {
544     EXTLIST r;
545     void *sym;
546
547     for( r = extensions; r; r = r->next )  {
548         int seq, class, vers;
549
550         if( r->failed )
551             continue;
552         if( !r->handle && load_extension(r) )
553             continue;
554         seq = 0;
555         while( (sym = (*r->enumfunc)(40, &seq, &class, &vers)) ) {
556             if( vers != 1 || class != 40 )
557                 continue;
558             return (int (*)(void (*)(const void*, size_t, int), int,
559                                                         size_t, int))sym;
560         }
561     }
562     return NULL;
563 }
564
565
566 void (*
567 _gcry_dynload_getfnc_fast_random_poll())( void (*)(const void*, size_t, int), int)
568 {
569     EXTLIST r;
570     void *sym;
571
572     for( r = extensions; r; r = r->next )  {
573         int seq, class, vers;
574
575         if( r->failed )
576             continue;
577         if( !r->handle && load_extension(r) )
578             continue;
579         seq = 0;
580         while( (sym = (*r->enumfunc)(41, &seq, &class, &vers)) ) {
581             if( vers != 1 || class != 41 )
582                 continue;
583             return (void (*)( void (*)(const void*, size_t, int), int))sym;
584         }
585     }
586     return NULL;
587 }
588