New. Taken from gnupg 1.9.
[gnupg.git] / scd / sc-investigate.c
1 /* sc-investigate.c - A tool to look around on smartcards.
2  *      Copyright (C) 2003 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
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #define JNLIB_NEED_LOG_LOGV
29 #include "scdaemon.h"
30 #include <gcrypt.h>
31
32 #include "apdu.h" /* for open_reader */
33 #include "atr.h"
34 #include "app-common.h"
35
36 #define _(a) (a)
37
38
39 enum cmd_and_opt_values 
40 { oVerbose        = 'v',
41   oReaderPort     = 500,
42   oDebug,
43   oDebugAll,
44
45   oGenRandom,
46
47 aTest };
48
49
50 static ARGPARSE_OPTS opts[] = {
51   
52   { 301, NULL, 0, "@Options:\n " },
53
54   { oVerbose, "verbose",   0, "verbose" },
55   { oReaderPort, "reader-port", 1, "|N|connect to reader at port N"},
56   { oDebug,     "debug"     ,4|16, "set debugging flags"},
57   { oDebugAll, "debug-all" ,0, "enable full debugging"},
58   { oGenRandom, "gen-random", 4, "|N|generate N bytes of random"},
59   {0}
60 };
61
62 static const char *
63 my_strusage (int level)
64 {
65   const char *p;
66   switch (level)
67     {
68     case 11: p = "sc-investigate (GnuPG)";
69       break;
70     case 13: p = VERSION; break;
71     case 17: p = PRINTABLE_OS_NAME; break;
72     case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
73       break;
74     case 1:
75     case 40: p =  _("Usage: sc-investigate [options] (-h for help)\n");
76       break;
77     case 41: p =  _("Syntax: sc-investigate [options] [args]]\n"
78                     "Have a look at smartcards\n");
79     break;
80     
81     default: p = NULL;
82     }
83   return p;
84 }
85
86 /* Used by gcry for logging */
87 static void
88 my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
89 {
90   /* translate the log levels */
91   switch (level)
92     {
93     case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
94     case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
95     case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
96     case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
97     case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
98     case GCRY_LOG_BUG:  level = JNLIB_LOG_BUG; break;
99     case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
100     default:            level = JNLIB_LOG_ERROR; break;  
101     }
102   log_logv (level, fmt, arg_ptr);
103 }
104
105
106 int
107 main (int argc, char **argv )
108 {
109   ARGPARSE_ARGS pargs;
110   int slot, rc;
111   int reader_port = 32768; /* First USB reader. */
112   struct app_ctx_s appbuf;
113   unsigned long gen_random = 0;
114
115   memset (&appbuf, 0, sizeof appbuf);
116
117   set_strusage (my_strusage);
118   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
119   log_set_prefix ("sc-investigate", 1); 
120
121   /* check that the libraries are suitable.  Do it here because
122      the option parsing may need services of the library */
123   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
124     {
125       log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
126                  NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
127     }
128
129   gcry_set_log_handler (my_gcry_logger, NULL);
130   /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/
131
132   pargs.argc = &argc;
133   pargs.argv = &argv;
134   pargs.flags=  1;  /* do not remove the args */
135   while (arg_parse (&pargs, opts) )
136     {
137       switch (pargs.r_opt)
138         {
139         case oVerbose: opt.verbose++; break;
140         case oDebug: opt.debug |= pargs.r.ret_ulong; break;
141         case oDebugAll: opt.debug = ~0; break;
142         case oGenRandom: gen_random = pargs.r.ret_ulong; break;
143         default : pargs.err = 2; break;
144         }
145     }
146   if (log_get_errorcount(0))
147     exit(2);
148
149   if (opt.verbose < 2)
150     opt.verbose = 2; /* hack to let select_openpgp print some info. */
151
152   if (argc)
153     usage (1);
154
155   slot = apdu_open_reader (reader_port);
156   if (slot == -1)
157     exit (1);
158   
159   if (!gen_random)
160     {
161       rc = atr_dump (slot, stdout); 
162       if (rc)
163         log_error ("can't dump ATR: %s\n", gpg_strerror (rc));
164     }
165
166   appbuf.slot = slot;
167   rc = app_select_openpgp (&appbuf, NULL, NULL);
168   if (rc)
169     log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc));
170   else
171     {
172       appbuf.initialized = 1;
173       log_info ("openpgp application selected\n");
174
175       if (gen_random)
176         {
177           size_t nbytes;
178           unsigned char *buffer;
179           
180           buffer = xmalloc (4096);
181           do 
182             {
183               nbytes = gen_random > 4096? 4096 : gen_random;
184               rc = app_get_challenge (&appbuf, nbytes, buffer);
185               if (rc)
186                 log_error ("app_get_challenge failed: %s\n",gpg_strerror (rc));
187               else
188                 {
189                   if (fwrite (buffer, nbytes, 1, stdout) != 1)
190                     log_error ("writing to stdout failed: %s\n",
191                                strerror (errno));
192                   gen_random -= nbytes;
193                 }
194             }
195           while (gen_random && !log_get_errorcount (0));
196           xfree (buffer);
197         }
198     }
199
200   return log_get_errorcount (0)? 2:0;
201 }
202
203
204
205 void
206 send_status_info (CTRL ctrl, const char *keyword, ...)
207 {
208   /* DUMMY */
209 }