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