~ubuntu-branches/ubuntu/precise/gnupg2/precise-proposed

« back to all changes in this revision

Viewing changes to agent/genkey.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* pksign.c - Generate a keypair
 
2
 *      Copyright (C) 2002, 2003, 2004 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
 
 
29
#include "agent.h"
 
30
#include "i18n.h"
 
31
 
 
32
static int
 
33
store_key (gcry_sexp_t private, const char *passphrase, int force)
 
34
{
 
35
  int rc;
 
36
  char *buf;
 
37
  size_t len;
 
38
  unsigned char grip[20];
 
39
  
 
40
  if ( !gcry_pk_get_keygrip (private, grip) )
 
41
    {
 
42
      log_error ("can't calculate keygrip\n");
 
43
      return gpg_error (GPG_ERR_GENERAL);
 
44
    }
 
45
 
 
46
  len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0);
 
47
  assert (len);
 
48
  buf = gcry_malloc_secure (len);
 
49
  if (!buf)
 
50
      return out_of_core ();
 
51
  len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len);
 
52
  assert (len);
 
53
 
 
54
  if (passphrase)
 
55
    {
 
56
      unsigned char *p;
 
57
 
 
58
      rc = agent_protect (buf, passphrase, &p, &len);
 
59
      if (rc)
 
60
        {
 
61
          xfree (buf);
 
62
          return rc;
 
63
        }
 
64
      xfree (buf);
 
65
      buf = p;
 
66
    }
 
67
 
 
68
  rc = agent_write_private_key (grip, buf, len, force);
 
69
  xfree (buf);
 
70
  return rc;
 
71
}
 
72
 
 
73
/* Callback function to compare the first entered PIN with the one
 
74
   currently being entered. */
 
75
static int
 
76
reenter_compare_cb (struct pin_entry_info_s *pi)
 
77
{
 
78
  const char *pin1 = pi->check_cb_arg;
 
79
 
 
80
  if (!strcmp (pin1, pi->pin))
 
81
    return 0; /* okay */
 
82
  return -1;
 
83
}
 
84
 
 
85
 
 
86
 
 
87
/* Generate a new keypair according to the parameters given in
 
88
   KEYPARAM */
 
89
int
 
90
agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
 
91
              membuf_t *outbuf) 
 
92
{
 
93
  gcry_sexp_t s_keyparam, s_key, s_private, s_public;
 
94
  struct pin_entry_info_s *pi, *pi2;
 
95
  int rc;
 
96
  size_t len;
 
97
  char *buf;
 
98
 
 
99
  rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen);
 
100
  if (rc)
 
101
    {
 
102
      log_error ("failed to convert keyparam: %s\n", gpg_strerror (rc));
 
103
      return gpg_error (GPG_ERR_INV_DATA);
 
104
    }
 
105
 
 
106
  /* Get the passphrase now, cause key generation may take a while. */
 
107
  {
 
108
    const char *text1 = _("Please enter the passphrase to%0A"
 
109
                               "to protect your new key");
 
110
    const char *text2 = _("Please re-enter this passphrase");
 
111
    const char *initial_errtext = NULL;
 
112
 
 
113
    pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
 
114
    pi2 = pi + (sizeof *pi + 100);
 
115
    pi->max_length = 100;
 
116
    pi->max_tries = 3;
 
117
    pi2->max_length = 100;
 
118
    pi2->max_tries = 3;
 
119
    pi2->check_cb = reenter_compare_cb;
 
120
    pi2->check_cb_arg = pi->pin;
 
121
 
 
122
  next_try:
 
123
    rc = agent_askpin (ctrl, text1, initial_errtext, pi);
 
124
    initial_errtext = NULL;
 
125
    if (!rc)
 
126
      {
 
127
        rc = agent_askpin (ctrl, text2, NULL, pi2);
 
128
        if (rc == -1)
 
129
          { /* The re-entered one did not match and the user did not
 
130
               hit cancel. */
 
131
            initial_errtext = _("does not match - try again");
 
132
            goto next_try;
 
133
          }
 
134
      }
 
135
    if (rc)
 
136
      return rc;
 
137
    if (!*pi->pin)
 
138
      {
 
139
        xfree (pi);
 
140
        pi = NULL; /* User does not want a passphrase. */
 
141
      }
 
142
  }
 
143
 
 
144
  rc = gcry_pk_genkey (&s_key, s_keyparam );
 
145
  gcry_sexp_release (s_keyparam);
 
146
  if (rc)
 
147
    {
 
148
      log_error ("key generation failed: %s\n", gpg_strerror (rc));
 
149
      xfree (pi);
 
150
      return rc;
 
151
    }
 
152
 
 
153
  /* break out the parts */
 
154
  s_private = gcry_sexp_find_token (s_key, "private-key", 0);
 
155
  if (!s_private)
 
156
    {
 
157
      log_error ("key generation failed: invalid return value\n");
 
158
      gcry_sexp_release (s_key);
 
159
      xfree (pi);
 
160
      return gpg_error (GPG_ERR_INV_DATA);
 
161
    }
 
162
  s_public = gcry_sexp_find_token (s_key, "public-key", 0);
 
163
  if (!s_public)
 
164
    {
 
165
      log_error ("key generation failed: invalid return value\n");
 
166
      gcry_sexp_release (s_private);
 
167
      gcry_sexp_release (s_key);
 
168
      xfree (pi);
 
169
      return gpg_error (GPG_ERR_INV_DATA);
 
170
    }
 
171
  gcry_sexp_release (s_key); s_key = NULL;
 
172
  
 
173
  /* store the secret key */
 
174
  if (DBG_CRYPTO)
 
175
    log_debug ("storing private key\n");
 
176
  rc = store_key (s_private, pi? pi->pin:NULL, 0);
 
177
  xfree (pi); pi = NULL;
 
178
  gcry_sexp_release (s_private);
 
179
  if (rc)
 
180
    {
 
181
      gcry_sexp_release (s_public);
 
182
      return rc;
 
183
    }
 
184
 
 
185
  /* return the public key */
 
186
  if (DBG_CRYPTO)
 
187
    log_debug ("returning public key\n");
 
188
  len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0);
 
189
  assert (len);
 
190
  buf = xtrymalloc (len);
 
191
  if (!buf)
 
192
    {
 
193
      gpg_error_t tmperr = out_of_core ();
 
194
      gcry_sexp_release (s_private);
 
195
      gcry_sexp_release (s_public);
 
196
      return tmperr;
 
197
    }
 
198
  len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len);
 
199
  assert (len);
 
200
  put_membuf (outbuf, buf, len);
 
201
  gcry_sexp_release (s_public);
 
202
  xfree (buf);
 
203
 
 
204
  return 0;
 
205
}
 
206
 
 
207
 
 
208
 
 
209
/* Apply a new passpahrse to the key S_SKEY and store it. */
 
210
int
 
211
agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey) 
 
212
{
 
213
  struct pin_entry_info_s *pi, *pi2;
 
214
  int rc;
 
215
 
 
216
  {
 
217
    const char *text1 = _("Please enter the new passphrase");
 
218
    const char *text2 = _("Please re-enter this passphrase");
 
219
    const char *initial_errtext = NULL;
 
220
 
 
221
    pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
 
222
    pi2 = pi + (sizeof *pi + 100);
 
223
    pi->max_length = 100;
 
224
    pi->max_tries = 3;
 
225
    pi2->max_length = 100;
 
226
    pi2->max_tries = 3;
 
227
    pi2->check_cb = reenter_compare_cb;
 
228
    pi2->check_cb_arg = pi->pin;
 
229
 
 
230
  next_try:
 
231
    rc = agent_askpin (ctrl, text1, initial_errtext, pi);
 
232
    if (!rc)
 
233
      {
 
234
        rc = agent_askpin (ctrl, text2, NULL, pi2);
 
235
        if (rc == -1)
 
236
          { /* The re-entered one did not match and the user did not
 
237
               hit cancel. */
 
238
            initial_errtext = _("does not match - try again");
 
239
            goto next_try;
 
240
          }
 
241
      }
 
242
    if (rc)
 
243
      return rc;
 
244
    if (!*pi->pin)
 
245
      {
 
246
        xfree (pi);
 
247
        pi = NULL; /* User does not want a passphrase. */
 
248
      }
 
249
  }
 
250
 
 
251
  rc = store_key (s_skey, pi? pi->pin:NULL, 1);
 
252
  xfree (pi);
 
253
  return 0;
 
254
}