1 /* certreqgen-ui.c - Simple user interface for certreqgen.c
2 * Copyright (C) 2007 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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 3 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
37 /* Prompt for lines and append them to MB. */
39 ask_mb_lines (membuf_t
*mb
, const char *prefix
)
46 answer
= tty_get ("> ");
51 put_membuf_str (mb
, prefix
);
52 put_membuf_str (mb
, answer
);
53 put_membuf (mb
, "\n", 1);
60 /* Helper to store stuff in a membuf. */
62 store_key_value_lf (membuf_t
*mb
, const char *key
, const char *value
)
64 put_membuf_str (mb
, key
);
65 put_membuf_str (mb
, value
);
66 put_membuf (mb
, "\n", 1);
69 /* Helper tp store a membuf create by mb_ask_lines into MB. Returns
72 store_mb_lines (membuf_t
*mb
, membuf_t
*lines
)
76 if (get_membuf_len (lines
))
78 put_membuf (lines
, "", 1);
79 p
= get_membuf (lines
, NULL
);
82 put_membuf_str (mb
, p
);
89 /* Chech whether we have a key for the key with HEXGRIP. Returns NULL
90 if not or a string describing the type of the key (RSA, ELG, DSA,
93 check_keygrip (ctrl_t ctrl
, const char *hexgrip
)
100 if (hexgrip
[0] == '&')
103 err
= gpgsm_agent_readkey (ctrl
, 0, hexgrip
, &public);
106 publiclen
= gcry_sexp_canon_len (public, 0, NULL
, NULL
);
108 get_pk_algo_from_canon_sexp (public, publiclen
, &algo
);
113 case GCRY_PK_RSA
: return "RSA";
114 case GCRY_PK_DSA
: return "DSA";
115 case GCRY_PK_ELG
: return "ELG";
116 case GCRY_PK_ECDSA
: return "ECDSA";
117 default: return NULL
;
122 /* This function is used to create a certificate request from the
123 command line. In the past the similar gpgsm-gencert.sh script has
124 been used for it; however that scripts requires a full Unix shell
125 and thus is not suitable for the Windows port. So here is the
126 re-implementation. */
128 gpgsm_gencertreq_tty (ctrl_t ctrl
, FILE *output_fp
)
135 char *keytype_buffer
= NULL
;
137 char *keygrip
= NULL
;
142 const char *keyusage
;
144 membuf_t mb_email
, mb_dns
, mb_uri
, mb_result
;
150 init_membuf (&mb_email
, 100);
151 init_membuf (&mb_dns
, 100);
152 init_membuf (&mb_uri
, 100);
153 init_membuf (&mb_result
, 512);
156 /* Get the type of the key. */
157 tty_printf (_("Please select what kind of key you want:\n"));
158 tty_printf (_(" (%d) RSA\n"), 1 );
159 tty_printf (_(" (%d) Existing key\n"), 2 );
160 tty_printf (_(" (%d) Existing key from card\n"), 3 );
165 answer
= tty_get (_("Your selection? "));
167 selection
= *answer
? atoi (answer
): 1;
169 while (!(selection
>= 1 && selection
<= 3));
172 /* Get size of the key. */
179 answer
= tty_getf (_("What keysize do you want? (%u) "), defbits
);
181 trim_spaces (answer
);
182 nbits
= *answer
? atoi (answer
): defbits
;
183 if (nbits
< minbits
|| nbits
> maxbits
)
184 tty_printf(_("%s keysizes must be in the range %u-%u\n"),
185 "RSA", minbits
, maxbits
);
189 tty_printf (_("Requested keysize is %u bits\n"), nbits
);
190 /* We round it up so that it better matches the word size. */
193 nbits
= ((nbits
+ 63) / 64) * 64;
194 tty_printf (_("rounded up to %u bits\n"), nbits
);
197 else if (method
== 2)
202 answer
= tty_get (_("Enter the keygrip: "));
204 trim_spaces (answer
);
208 else if (strlen (answer
) != 40 &&
209 !(answer
[0] == '&' && strlen (answer
+1) == 40))
210 tty_printf (_("Not a valid keygrip (expecting 40 hex digits)\n"));
211 else if (!(keytype
= check_keygrip (ctrl
, answer
)) )
212 tty_printf (_("No key with this keygrip\n"));
219 nbits
= 1024; /* A dummy value is sufficient. */
221 else /* method == 3 */
224 strlist_t keypairlist
, sl
;
227 err
= gpgsm_agent_scd_serialno (ctrl
, &serialno
);
230 tty_printf (_("error reading the card: %s\n"), gpg_strerror (err
));
233 tty_printf (_("Serial number of the card: %s\n"), serialno
);
236 err
= gpgsm_agent_scd_keypairinfo (ctrl
, &keypairlist
);
239 tty_printf (_("error reading the card: %s\n"), gpg_strerror (err
));
245 tty_printf (_("Available keys:\n"));
246 for (count
=1,sl
=keypairlist
; sl
; sl
= sl
->next
, count
++)
247 tty_printf (" (%d) %s\n", count
, sl
->d
);
249 answer
= tty_get (_("Your selection? "));
251 trim_spaces (answer
);
252 selection
= atoi (answer
);
254 while (!(selection
> 0 && selection
< count
));
256 for (count
=1,sl
=keypairlist
; sl
; sl
= sl
->next
, count
++)
257 if (count
== selection
)
261 while (*s
&& !spacep (s
))
268 xfree (keytype_buffer
);
269 keytype_buffer
= xasprintf ("card:%s", s
);
270 free_strlist (keypairlist
);
271 keytype
= keytype_buffer
;
272 nbits
= 1024; /* A dummy value is sufficient. */
275 /* Ask for the key usage. */
276 tty_printf (_("Possible actions for a %s key:\n"), "RSA");
277 tty_printf (_(" (%d) sign, encrypt\n"), 1 );
278 tty_printf (_(" (%d) sign\n"), 2 );
279 tty_printf (_(" (%d) encrypt\n"), 3 );
283 answer
= tty_get (_("Your selection? "));
285 trim_spaces (answer
);
286 selection
= *answer
? atoi (answer
): 1;
289 case 1: keyusage
= "sign, encrypt"; break;
290 case 2: keyusage
= "sign"; break;
291 case 3: keyusage
= "encrypt"; break;
292 default: keyusage
= NULL
; break;
297 /* Get the subject name. */
300 size_t erroff
, errlen
;
303 answer
= tty_get (_("Enter the X.509 subject name: "));
305 trim_spaces (answer
);
307 tty_printf (_("No subject name given\n"));
308 else if ( (err
= ksba_dn_teststr (answer
, 0, &erroff
, &errlen
)) )
310 if (gpg_err_code (err
) == GPG_ERR_UNKNOWN_NAME
)
311 tty_printf (_("Invalid subject name label `%.*s'\n"),
312 (int)errlen
, answer
+erroff
);
315 /* TRANSLATORS: The 22 in the second string is the
316 length of the first string up to the "%s". Please
317 adjust it do the length of your translation. The
318 second string is merely passed to atoi so you can
319 drop everything after the number. */
320 tty_printf (_("Invalid subject name `%s'\n"), answer
);
321 tty_printf ("%*s^\n",
322 atoi (_("22 translator: see "
323 "certreg-ui.c:gpgsm_gencertreq_tty"))
330 subject_name
= answer
;
333 /* Get the email addresses. */
334 tty_printf (_("Enter email addresses"));
335 tty_printf (_(" (end with an empty line):\n"));
336 ask_mb_lines (&mb_email
, "Name-Email: ");
339 tty_printf (_("Enter DNS names"));
340 tty_printf (_(" (optional; end with an empty line):\n"));
341 ask_mb_lines (&mb_email
, "Name-DNS: ");
344 tty_printf (_("Enter URIs"));
345 tty_printf (_(" (optional; end with an empty line):\n"));
346 ask_mb_lines (&mb_email
, "Name-URI: ");
349 /* Put it all together. */
350 store_key_value_lf (&mb_result
, "Key-Type: ", keytype
);
353 snprintf (numbuf
, sizeof numbuf
, "%u", nbits
);
354 store_key_value_lf (&mb_result
, "Key-Length: ", numbuf
);
356 store_key_value_lf (&mb_result
, "Key-Usage: ", keyusage
);
357 store_key_value_lf (&mb_result
, "Name-DN: ", subject_name
);
359 store_key_value_lf (&mb_result
, "Key-Grip: ", keygrip
);
360 if (store_mb_lines (&mb_result
, &mb_email
))
362 if (store_mb_lines (&mb_result
, &mb_dns
))
364 if (store_mb_lines (&mb_result
, &mb_uri
))
366 put_membuf (&mb_result
, "", 1);
367 result
= get_membuf (&mb_result
, NULL
);
371 tty_printf (_("Parameters to be used for the certificate request:\n"));
372 for (s
=result
; (s2
= strchr (s
, '\n')); s
= s2
+1, i
++)
373 tty_printf (" %.*s\n", (int)(s2
-s
), s
);
377 if (!tty_get_answer_is_yes ("Really create request? (y/N) "))
380 /* Now create a parameter file and generate the key. */
381 fp
= es_fopenmem (0, "w+");
384 log_error (_("error creating temporary file: %s\n"), strerror (errno
));
387 es_fputs (result
, fp
);
389 tty_printf (_("Now creating certificate request. "
390 "This may take a while ...\n"));
392 int save_pem
= ctrl
->create_pem
;
393 ctrl
->create_pem
= 1; /* Force creation of PEM. */
394 err
= gpgsm_genkey (ctrl
, fp
, output_fp
);
395 ctrl
->create_pem
= save_pem
;
398 tty_printf (_("Ready. You should now send this request to your CA.\n"));
403 log_error (_("resource problem: out of core\n"));
407 xfree (subject_name
);
408 xfree (keytype_buffer
);
410 xfree (get_membuf (&mb_email
, NULL
));
411 xfree (get_membuf (&mb_dns
, NULL
));
412 xfree (get_membuf (&mb_uri
, NULL
));
413 xfree (get_membuf (&mb_result
, NULL
));