1 /* certreqgen-ui.c - Simple user interface for certreqgen.c
2 * Copyright (C) 2007, 2010, 2011 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 <https://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, &algostr);
113 else if (!strcmp (algostr, "rsa"))
115 else if (!strcmp (algostr, "dsa"))
117 else if (!strcmp (algostr, "elg"))
119 else if (!strcmp (algostr, "ecdsa"))
126 /* This function is used to create a certificate request from the
127 command line. In the past the similar gpgsm-gencert.sh script has
128 been used for it; however that scripts requires a full Unix shell
129 and thus is not suitable for the Windows port. So here is the
130 re-implementation. */
132 gpgsm_gencertreq_tty (ctrl_t ctrl, estream_t output_stream)
139 char *keytype_buffer = NULL;
141 char *keygrip = NULL;
146 const char *keyusage;
148 membuf_t mb_email, mb_dns, mb_uri, mb_result;
154 init_membuf (&mb_email, 100);
155 init_membuf (&mb_dns, 100);
156 init_membuf (&mb_uri, 100);
157 init_membuf (&mb_result, 512);
160 /* Get the type of the key. */
161 tty_printf (_("Please select what kind of key you want:\n"));
162 tty_printf (_(" (%d) RSA\n"), 1 );
163 tty_printf (_(" (%d) Existing key\n"), 2 );
164 tty_printf (_(" (%d) Existing key from card\n"), 3 );
169 answer = tty_get (_("Your selection? "));
171 selection = *answer? atoi (answer): 1;
173 while (!(selection >= 1 && selection <= 3));
176 /* Get size of the key. */
183 answer = tty_getf (_("What keysize do you want? (%u) "), defbits);
185 trim_spaces (answer);
186 nbits = *answer? atoi (answer): defbits;
187 if (nbits < minbits || nbits > maxbits)
188 tty_printf(_("%s keysizes must be in the range %u-%u\n"),
189 "RSA", minbits, maxbits);
193 tty_printf (_("Requested keysize is %u bits\n"), nbits);
194 /* We round it up so that it better matches the word size. */
197 nbits = ((nbits + 63) / 64) * 64;
198 tty_printf (_("rounded up to %u bits\n"), nbits);
201 else if (method == 2)
206 answer = tty_get (_("Enter the keygrip: "));
208 trim_spaces (answer);
212 else if (strlen (answer) != 40 &&
213 !(answer[0] == '&' && strlen (answer+1) == 40))
214 tty_printf (_("Not a valid keygrip (expecting 40 hex digits)\n"));
215 else if (!(keytype = check_keygrip (ctrl, answer)) )
216 tty_printf (_("No key with this keygrip\n"));
223 nbits = 1024; /* A dummy value is sufficient. */
225 else /* method == 3 */
228 strlist_t keypairlist, sl;
231 err = gpgsm_agent_scd_serialno (ctrl, &serialno);
234 tty_printf (_("error reading the card: %s\n"), gpg_strerror (err));
237 tty_printf (_("Serial number of the card: %s\n"), serialno);
240 err = gpgsm_agent_scd_keypairinfo (ctrl, &keypairlist);
243 tty_printf (_("error reading the card: %s\n"), gpg_strerror (err));
249 tty_printf (_("Available keys:\n"));
250 for (count=1,sl=keypairlist; sl; sl = sl->next, count++)
251 tty_printf (" (%d) %s\n", count, sl->d);
253 answer = tty_get (_("Your selection? "));
255 trim_spaces (answer);
256 selection = atoi (answer);
258 while (!(selection > 0 && selection < count));
260 for (count=1,sl=keypairlist; sl; sl = sl->next, count++)
261 if (count == selection)
265 while (*s && !spacep (s))
272 xfree (keytype_buffer);
273 keytype_buffer = xasprintf ("card:%s", s);
274 free_strlist (keypairlist);
275 keytype = keytype_buffer;
276 nbits = 1024; /* A dummy value is sufficient. */
279 /* Ask for the key usage. */
280 tty_printf (_("Possible actions for a %s key:\n"), "RSA");
281 tty_printf (_(" (%d) sign, encrypt\n"), 1 );
282 tty_printf (_(" (%d) sign\n"), 2 );
283 tty_printf (_(" (%d) encrypt\n"), 3 );
287 answer = tty_get (_("Your selection? "));
289 trim_spaces (answer);
290 selection = *answer? atoi (answer): 1;
293 case 1: keyusage = "sign, encrypt"; break;
294 case 2: keyusage = "sign"; break;
295 case 3: keyusage = "encrypt"; break;
296 default: keyusage = NULL; break;
301 /* Get the subject name. */
304 size_t erroff, errlen;
307 answer = tty_get (_("Enter the X.509 subject name: "));
309 trim_spaces (answer);
311 tty_printf (_("No subject name given\n"));
312 else if ( (err = ksba_dn_teststr (answer, 0, &erroff, &errlen)) )
314 if (gpg_err_code (err) == GPG_ERR_UNKNOWN_NAME)
315 tty_printf (_("Invalid subject name label '%.*s'\n"),
316 (int)errlen, answer+erroff);
319 /* TRANSLATORS: The 22 in the second string is the
320 length of the first string up to the "%s". Please
321 adjust it do the length of your translation. The
322 second string is merely passed to atoi so you can
323 drop everything after the number. */
324 tty_printf (_("Invalid subject name '%s'\n"), answer);
325 tty_printf ("%*s^\n",
326 atoi (_("22 translator: see "
327 "certreg-ui.c:gpgsm_gencertreq_tty"))
334 subject_name = answer;
337 /* Get the email addresses. */
338 tty_printf (_("Enter email addresses"));
339 tty_printf (_(" (end with an empty line):\n"));
340 ask_mb_lines (&mb_email, "Name-Email: ");
343 tty_printf (_("Enter DNS names"));
344 tty_printf (_(" (optional; end with an empty line):\n"));
345 ask_mb_lines (&mb_dns, "Name-DNS: ");
348 tty_printf (_("Enter URIs"));
349 tty_printf (_(" (optional; end with an empty line):\n"));
350 ask_mb_lines (&mb_uri, "Name-URI: ");
353 /* Want a self-signed certificate? */
354 selfsigned = tty_get_answer_is_yes
355 (_("Create self-signed certificate? (y/N) "));
358 /* Put it all together. */
359 store_key_value_lf (&mb_result, "Key-Type: ", keytype);
362 snprintf (numbuf, sizeof numbuf, "%u", nbits);
363 store_key_value_lf (&mb_result, "Key-Length: ", numbuf);
366 store_key_value_lf (&mb_result, "Key-Grip: ", keygrip);
367 store_key_value_lf (&mb_result, "Key-Usage: ", keyusage);
369 store_key_value_lf (&mb_result, "Serial: ", "random");
370 store_key_value_lf (&mb_result, "Name-DN: ", subject_name);
371 if (store_mb_lines (&mb_result, &mb_email))
373 if (store_mb_lines (&mb_result, &mb_dns))
375 if (store_mb_lines (&mb_result, &mb_uri))
377 put_membuf (&mb_result, "", 1);
378 result = get_membuf (&mb_result, NULL);
382 tty_printf (_("These parameters are used:\n"));
383 for (s=result; (s2 = strchr (s, '\n')); s = s2+1)
384 tty_printf (" %.*s\n", (int)(s2-s), s);
387 if (!tty_get_answer_is_yes ("Proceed with creation? (y/N) "))
390 /* Now create a parameter file and generate the key. */
391 fp = es_fopenmem (0, "w+");
394 log_error (_("error creating temporary file: %s\n"), strerror (errno));
397 es_fputs (result, fp);
400 tty_printf ("%s", _("Now creating self-signed certificate. "));
402 tty_printf ("%s", _("Now creating certificate request. "));
403 tty_printf ("%s", _("This may take a while ...\n"));
406 int save_pem = ctrl->create_pem;
407 ctrl->create_pem = 1; /* Force creation of PEM. */
408 err = gpgsm_genkey (ctrl, fp, output_stream);
409 ctrl->create_pem = save_pem;
414 tty_printf (_("Ready.\n"));
417 (_("Ready. You should now send this request to your CA.\n"));
423 log_error (_("resource problem: out of core\n"));
427 xfree (subject_name);
428 xfree (keytype_buffer);
430 xfree (get_membuf (&mb_email, NULL));
431 xfree (get_membuf (&mb_dns, NULL));
432 xfree (get_membuf (&mb_uri, NULL));
433 xfree (get_membuf (&mb_result, NULL));