* genkey.c (store_key): Protect the key.
[gnupg.git] / agent / findkey.c
1 /* findkey.c - locate the secret key
2  *      Copyright (C) 2001 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 <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30
31 #include "agent.h"
32
33 static int
34 unprotect (unsigned char **keybuf)
35 {
36   struct pin_entry_info_s *pi;
37   int rc;
38   unsigned char *result;
39   size_t resultlen;
40   int tries = 0;
41
42   /* fixme: check whether the key needs unprotection */
43
44   pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
45   pi->max_length = 100;
46   pi->min_digits = 0;  /* we want a real passphrase */
47   pi->max_digits = 8;
48   pi->max_tries = 3;
49
50   do
51     {
52       rc = agent_askpin (NULL, NULL, pi);
53       if (!rc)
54         {
55           rc = agent_unprotect (*keybuf, pi->pin, &result, &resultlen);
56           if (!rc)
57             {
58               xfree (*keybuf);
59               *keybuf = result;
60               xfree (pi);
61               return 0;
62             }
63         }
64     }
65   while ((rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
66          && tries++ < 3);
67   xfree (pi);
68   return rc;
69 }
70
71
72
73 /* Return the secret key as an S-Exp after locating it using the grip.
74    Returns NULL if key is not available. */
75 GCRY_SEXP
76 agent_key_from_file (const unsigned char *grip)
77 {
78   int i, rc;
79   char *fname;
80   FILE *fp;
81   struct stat st;
82   unsigned char *buf;
83   size_t len, buflen, erroff;
84   GCRY_SEXP s_skey;
85   char hexgrip[41];
86   
87   for (i=0; i < 20; i++)
88     sprintf (hexgrip+2*i, "%02X", grip[i]);
89   hexgrip[40] = 0;
90
91   fname = make_filename (opt.homedir, "private-keys-v1.d", hexgrip, NULL );
92   fp = fopen (fname, "rb");
93   if (!fp)
94     {
95       log_error ("can't open `%s': %s\n", fname, strerror (errno));
96       xfree (fname);
97       return NULL;
98     }
99   
100   if (fstat (fileno(fp), &st))
101     {
102       log_error ("can't stat `%s': %s\n", fname, strerror (errno));
103       xfree (fname);
104       fclose (fp);
105       return NULL;
106     }
107
108   buflen = st.st_size;
109   buf = xmalloc (buflen+1);
110   if (fread (buf, buflen, 1, fp) != 1)
111     {
112       log_error ("error reading `%s': %s\n", fname, strerror (errno));
113       xfree (fname);
114       fclose (fp);
115       xfree (buf);
116       return NULL;
117     }
118
119   rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen);
120   xfree (fname);
121   fclose (fp);
122   xfree (buf);
123   if (rc)
124     {
125       log_error ("failed to build S-Exp (off=%u): %s\n",
126                  (unsigned int)erroff, gcry_strerror (rc));
127       return NULL;
128     }
129   len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
130   assert (len);
131   buf = xtrymalloc (len);
132   if (!buf)
133     {
134       gcry_sexp_release (s_skey);
135       return NULL;
136     }
137   len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len);
138   assert (len);
139   gcry_sexp_release (s_skey);
140
141   rc = unprotect (&buf);
142   if (rc)
143     {
144       log_error ("failed to unprotect the secret key: %s\n",
145                  gcry_strerror (rc));
146       xfree (buf);
147       return NULL;
148     }
149
150   /* arggg FIXME: does scna support secure memory? */
151   rc = gcry_sexp_sscan (&s_skey, &erroff,
152                         buf, gcry_sexp_canon_len (buf, 0, NULL, NULL));
153   xfree (buf);
154   if (rc)
155     {
156       log_error ("failed to build S-Exp (off=%u): %s\n",
157                  (unsigned int)erroff, gcry_strerror (rc));
158       return NULL;
159     }
160
161   return s_skey;
162 }
163
164 /* Return the secret key as an S-Exp after locating it using the grip.
165    Returns NULL if key is not available. 0 = key is available */
166 int
167 agent_key_available (const unsigned char *grip)
168 {
169   int i;
170   char *fname;
171   char hexgrip[41];
172   
173   for (i=0; i < 20; i++)
174     sprintf (hexgrip+2*i, "%02X", grip[i]);
175   hexgrip[40] = 0;
176
177   fname = make_filename (opt.homedir, "private-keys-v1.d", hexgrip, NULL );
178   i = !access (fname, R_OK)? 0 : -1;
179   xfree (fname);
180   return i;
181 }
182
183
184