Add Kludge for RegTP sillyness.
[gnupg.git] / sm / certreqgen.c
1 /* certreqgen.c - Generate a key and a certification request
2  *      Copyright (C) 2002, 2003, 2005 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 /*
22 The format of the native parameter file is follows:
23   o Text only, line length is limited to about 1000 chars.
24   o You must use UTF-8 encoding to specify non-ascii characters.
25   o Empty lines are ignored.
26   o Leading and trailing spaces are ignored.
27   o A hash sign as the first non white space character is a comment line.
28   o Control statements are indicated by a leading percent sign, the
29     arguments are separated by white space from the keyword.
30   o Parameters are specified by a keyword, followed by a colon.  Arguments
31     are separated by white space.
32   o The first parameter must be "Key-Type", control statements
33     may be placed anywhere.
34   o Key generation takes place when either the end of the parameter file
35     is reached, the next "Key-Type" parameter is encountered or at the
36     controlstatement "%commit"
37   o Control statements:
38     %echo <text>
39         Print <text>.
40     %dry-run
41         Suppress actual key generation (useful for syntax checking).
42     %commit
43         Perform the key generation.  Note that an implicit commit is done
44         at the next "Key-Type" parameter.
45     %certfile <filename>
46         Do not write the certificate to the keyDB but to <filename>.
47         This must be given before the first
48         commit to take place, duplicate specification of the same filename
49         is ignored, the last filename before a commit is used.
50         The filename is used until a new filename is used (at commit points)
51         and all keys are written to that file.  If a new filename is given,
52         this file is created (and overwrites an existing one).
53         Both control statements must be given.
54    o The order of the parameters does not matter except for "Key-Type"
55      which must be the first parameter.  The parameters are only for the
56      generated keyblock and parameters from previous key generations are not
57      used. Some syntactically checks may be performed.
58      The currently defined parameters are:
59      Key-Type: <algo>
60         Starts a new parameter block by giving the type of the
61         primary key. The algorithm must be capable of signing.
62         This is a required parameter.  For now the only supported
63         algorithm is "rsa".
64      Key-Length: <length-in-bits>
65         Length of the key in bits.  Default is 1024.
66      Key-Grip: hexstring
67         This is optional and used to generate a request for an already
68         existsing key.  Key-Length will be ignored when given,
69      Key-Usage: <usage-list>
70         Space or comma delimited list of key usage, allowed values are
71         "encrypt" and "sign".  This is used to generate the KeyUsage extension.
72         Please make sure that the algorithm is capable of this usage.  Default
73         is to allow encrypt and sign.
74      Name-DN: subject name
75         This is the DN name of the subject in rfc2253 format.
76      Name-Email: <string>
77         The is an email address for the altSubjectName
78      Name-DNS: <string> 
79         The is an DNS name for the altSubjectName
80      Name-URI: <string> 
81         The is an URI for the altSubjectName
82
83 Here is an example:
84 $ cat >foo <<EOF
85 %echo Generating a standard key
86 Key-Type: RSA
87 Key-Length: 1024
88 Name-DN: CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE
89 Name-Email: joe@foo.bar
90 # Do a commit here, so that we can later print "done" :-)
91 %commit
92 %echo done
93 EOF
94 */
95
96
97 #include <config.h>
98 #include <stdio.h>
99 #include <stdlib.h>
100 #include <string.h>
101 #include <errno.h>
102 #include <unistd.h> 
103 #include <time.h>
104 #include <assert.h>
105
106 #include "gpgsm.h"
107 #include <gcrypt.h>
108 #include <ksba.h>
109
110 #include "keydb.h"
111 #include "i18n.h"
112
113
114 enum para_name {
115   pKEYTYPE,
116   pKEYLENGTH,
117   pKEYGRIP,
118   pKEYUSAGE,
119   pNAMEDN,
120   pNAMEEMAIL,
121   pNAMEDNS,
122   pNAMEURI
123 };
124
125 struct para_data_s {
126   struct para_data_s *next;
127   int lnr;
128   enum para_name key;
129   union {
130     unsigned int usage; 
131     char value[1];
132   } u;
133 };
134
135 struct reqgen_ctrl_s {
136   int lnr;
137   int dryrun;
138   ksba_writer_t writer;
139 };
140
141
142 static const char oidstr_keyUsage[] = "2.5.29.15";
143
144
145 static int proc_parameters (ctrl_t ctrl,
146                             struct para_data_s *para,
147                             struct reqgen_ctrl_s *outctrl);
148 static int create_request (ctrl_t ctrl,
149                            struct para_data_s *para,
150                            ksba_const_sexp_t public,
151                            struct reqgen_ctrl_s *outctrl);
152
153
154 \f
155 static void
156 release_parameter_list (struct para_data_s *r)
157 {
158   struct para_data_s *r2;
159   
160   for (; r ; r = r2)
161     {
162       r2 = r->next;
163       xfree(r);
164     }
165 }
166
167 static struct para_data_s *
168 get_parameter (struct para_data_s *para, enum para_name key, int seq)
169 {
170   struct para_data_s *r;
171   
172   for (r = para; r ; r = r->next)
173     if ( r->key == key && !seq--)
174       return r;
175   return NULL;
176 }
177
178 static const char *
179 get_parameter_value (struct para_data_s *para, enum para_name key, int seq)
180 {
181   struct para_data_s *r = get_parameter (para, key, seq);
182   return (r && *r->u.value)? r->u.value : NULL;
183 }
184
185 static int
186 get_parameter_algo (struct para_data_s *para, enum para_name key)
187 {
188   struct para_data_s *r = get_parameter (para, key, 0);
189   if (!r)
190     return -1;
191   if (digitp (r->u.value))
192     return atoi( r->u.value );
193   return gcry_pk_map_name (r->u.value); 
194 }
195
196 /* Parse the usage parameter.  Returns 0 on success.  Note that we
197    only care about sign and encrypt and don't (yet) allow all the
198    other X.509 usage to be specified; instead we will use a fixed
199    mapping to the X.509 usage flags. */
200 static int
201 parse_parameter_usage (struct para_data_s *para, enum para_name key)
202 {
203   struct para_data_s *r = get_parameter (para, key, 0);
204   char *p, *pn;
205   unsigned int use;
206   
207   if (!r)
208     return 0; /* none (this is an optional parameter)*/
209     
210   use = 0;
211   pn = r->u.value;
212   while ( (p = strsep (&pn, " \t,")) )
213     {
214       if (!*p)
215         ;
216       else if ( !ascii_strcasecmp (p, "sign") )
217         use |= GCRY_PK_USAGE_SIGN;
218       else if ( !ascii_strcasecmp (p, "encrypt") )
219         use |= GCRY_PK_USAGE_ENCR;
220       else
221         {
222           log_error ("line %d: invalid usage list\n", r->lnr);
223           return -1; /* error */
224         }
225     }
226   r->u.usage = use;
227   return 0;
228 }
229
230
231 static unsigned int
232 get_parameter_uint (struct para_data_s *para, enum para_name key)
233 {
234   struct para_data_s *r = get_parameter (para, key, 0);
235
236   if (!r)
237     return 0;
238
239   if (r->key == pKEYUSAGE)
240     return r->u.usage;
241
242   return (unsigned int)strtoul (r->u.value, NULL, 10);
243 }
244
245
246
247 /* Read the certificate generation parameters from FP and generate
248    (all) certificate requests.  */
249 static int
250 read_parameters (ctrl_t ctrl, FILE *fp, ksba_writer_t writer)
251 {
252   static struct {
253     const char *name;
254     enum para_name key;
255     int allow_dups;
256   } keywords[] = {
257     { "Key-Type",       pKEYTYPE},
258     { "Key-Length",     pKEYLENGTH },
259     { "Key-Grip",       pKEYGRIP },
260     { "Key-Usage",      pKEYUSAGE },
261     { "Name-DN",        pNAMEDN },
262     { "Name-Email",     pNAMEEMAIL, 1 },
263     { "Name-DNS",       pNAMEDNS, 1 },
264     { "Name-URI",       pNAMEURI, 1 },
265     { NULL, 0 }
266   };
267   char line[1024], *p;
268   const char *err = NULL;
269   struct para_data_s *para, *r;
270   int i, rc = 0, any = 0;
271   struct reqgen_ctrl_s outctrl;
272
273   memset (&outctrl, 0, sizeof (outctrl));
274   outctrl.writer = writer;
275
276   err = NULL;
277   para = NULL;
278   while (fgets (line, DIM(line)-1, fp) )
279     {
280       char *keyword, *value;
281
282       outctrl.lnr++;
283       if (*line && line[strlen(line)-1] != '\n')
284         {
285           err = "line too long";
286           break;
287         }
288       for (p=line; spacep (p); p++)
289         ;
290       if (!*p || *p == '#')
291         continue;
292
293       keyword = p;
294       if (*keyword == '%')
295         {
296           for (; *p && !spacep (p); p++)
297             ;
298           if (*p)
299             *p++ = 0;
300           for (; spacep (p); p++)
301             ;
302           value = p;
303           trim_trailing_spaces (value);
304
305           if (!ascii_strcasecmp (keyword, "%echo"))
306             log_info ("%s\n", value);
307           else if (!ascii_strcasecmp (keyword, "%dry-run"))
308             outctrl.dryrun = 1;
309           else if (!ascii_strcasecmp( keyword, "%commit"))
310             {
311               rc = proc_parameters (ctrl, para, &outctrl);
312               if (rc)
313                 goto leave;
314               any = 1;
315               release_parameter_list (para);
316               para = NULL;
317             }
318           else
319             log_info ("skipping control `%s' (%s)\n", keyword, value);
320
321           continue;
322         }
323
324
325       if (!(p = strchr (p, ':')) || p == keyword)
326         {
327           err = "missing colon";
328           break;
329         }
330       if (*p)
331         *p++ = 0;
332       for (; spacep (p); p++)
333         ;
334       if (!*p)
335         {
336           err = "missing argument";
337           break;
338         }
339       value = p;
340       trim_trailing_spaces (value);
341
342       for (i=0; (keywords[i].name
343                  && ascii_strcasecmp (keywords[i].name, keyword)); i++)
344         ;
345       if (!keywords[i].name)
346         {
347           err = "unknown keyword";
348           break;
349         }
350       if (keywords[i].key != pKEYTYPE && !para)
351         {
352           err = "parameter block does not start with \"Key-Type\"";
353           break;
354         }
355
356       if (keywords[i].key == pKEYTYPE && para)
357         {
358           rc = proc_parameters (ctrl, para, &outctrl);
359           if (rc)
360             goto leave;
361           any = 1;
362           release_parameter_list (para);
363           para = NULL;
364         }
365       else if (!keywords[i].allow_dups)
366         {
367           for (r = para; r && r->key != keywords[i].key; r = r->next)
368             ;
369           if (r)
370             {
371               err = "duplicate keyword";
372               break;
373             }
374         }
375
376       r = xtrycalloc (1, sizeof *r + strlen( value ));
377       if (!r)
378         {
379           err = "out of core";
380           break;
381         }
382       r->lnr = outctrl.lnr;
383       r->key = keywords[i].key;
384       strcpy (r->u.value, value);
385       r->next = para;
386       para = r;
387     }
388
389   if (err)
390     {
391       log_error ("line %d: %s\n", outctrl.lnr, err);
392       rc = gpg_error (GPG_ERR_GENERAL);
393     }
394   else if (ferror(fp))
395     {
396       log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) );
397       rc = gpg_error (GPG_ERR_GENERAL);
398     }
399   else if (para)
400     {
401       rc = proc_parameters (ctrl, para, &outctrl);
402       if (rc)
403         goto leave;
404       any = 1;
405     }
406
407   if (!rc && !any)
408     rc = gpg_error (GPG_ERR_NO_DATA);
409
410  leave:
411   release_parameter_list (para);
412   return rc;
413 }
414
415 /* check whether there are invalid characters in the email address S */
416 static int
417 has_invalid_email_chars (const char *s)
418 {
419   int at_seen=0;
420   static char valid_chars[] = "01234567890_-."
421                               "abcdefghijklmnopqrstuvwxyz"
422                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
423   for (; *s; s++)
424     {
425       if (*s & 0x80)
426         return 1;
427       if (*s == '@')
428         at_seen++;
429       else if (!at_seen && !( !!strchr (valid_chars, *s) || *s == '+'))
430         return 1;
431       else if (at_seen && !strchr (valid_chars, *s))
432         return 1;
433     }
434   return at_seen != 1;
435 }
436
437
438 /* Check that all required parameters are given and perform the action */
439 static int
440 proc_parameters (ctrl_t ctrl,
441                  struct para_data_s *para, struct reqgen_ctrl_s *outctrl)
442 {
443   struct para_data_s *r;
444   const char *s;
445   int i;
446   unsigned int nbits;
447   char numbuf[20];
448   unsigned char keyparms[100];
449   int rc;
450   ksba_sexp_t public;
451   int seq;
452   
453   /* check that we have all required parameters */
454   assert (get_parameter (para, pKEYTYPE, 0));
455
456   /* We can only use RSA for now.  There is a with pkcs-10 on how to
457      use ElGamal because it is expected that a PK algorithm can always
458      be used for signing. */
459   i = get_parameter_algo (para, pKEYTYPE);
460   if (i < 1 || i != GCRY_PK_RSA )
461     {
462       r = get_parameter (para, pKEYTYPE, 0);
463       log_error (_("line %d: invalid algorithm\n"), r->lnr);
464       return gpg_error (GPG_ERR_INV_PARAMETER);
465     }
466   
467   /* check the keylength */
468   if (!get_parameter (para, pKEYLENGTH, 0))
469     nbits = 1024;
470   else
471     nbits = get_parameter_uint (para, pKEYLENGTH);
472   if (nbits < 1024 || nbits > 4096)
473     {
474       /* The BSI specs dated 2002-11-25 don't allow lengths below 1024. */
475       r = get_parameter (para, pKEYLENGTH, 0);
476       log_error (_("line %d: invalid key length %u (valid are %d to %d)\n"),
477                  r->lnr, nbits, 1024, 4096);
478       return gpg_error (GPG_ERR_INV_PARAMETER);
479     }
480     
481   /* check the usage */
482   if (parse_parameter_usage (para, pKEYUSAGE))
483     return gpg_error (GPG_ERR_INV_PARAMETER);
484
485   /* check that there is a subject name and that this DN fits our
486      requirements */
487   if (!(s=get_parameter_value (para, pNAMEDN, 0)))
488     {
489       r = get_parameter (para, pKEYTYPE, 0);
490       log_error (_("line %d: no subject name given\n"), r->lnr);
491       return gpg_error (GPG_ERR_INV_PARAMETER);
492     }
493   /* fixme check s */
494
495   /* check that the optional email address is okay */
496   for (seq=0; (s=get_parameter_value (para, pNAMEEMAIL, seq)); seq++)
497     { 
498       if (has_invalid_email_chars (s)
499           || *s == '@'
500           || s[strlen(s)-1] == '@'
501           || s[strlen(s)-1] == '.'
502           || strstr(s, ".."))
503         {
504           r = get_parameter (para, pNAMEEMAIL, seq);
505           log_error (_("line %d: not a valid email address\n"), r->lnr);
506           return gpg_error (GPG_ERR_INV_PARAMETER);
507         }
508     }
509
510   s = get_parameter_value (para, pKEYGRIP, 0);
511   if (s) /* Use existing key.  */
512     {
513       rc = gpgsm_agent_readkey (ctrl, s, &public);
514       if (rc)
515         {
516           r = get_parameter (para, pKEYTYPE, 0);
517           log_error (_("line %d: error getting key by keygrip `%s': %s\n"),
518                      r->lnr, s, gpg_strerror (rc));
519           return rc;
520         }
521     }
522   else /* Generate new key.  */
523     {
524       sprintf (numbuf, "%u", nbits);
525       snprintf ((char*)keyparms, DIM (keyparms)-1, 
526                 "(6:genkey(3:rsa(5:nbits%d:%s)))",
527                 (int)strlen (numbuf), numbuf);
528       rc = gpgsm_agent_genkey (ctrl, keyparms, &public);
529       if (rc)
530         {
531           r = get_parameter (para, pKEYTYPE, 0);
532           log_error (_("line %d: key generation failed: %s\n"),
533                      r->lnr, gpg_strerror (rc));
534           return rc;
535         }
536     }
537
538   rc = create_request (ctrl, para, public, outctrl);
539   xfree (public);
540
541   return rc;
542 }
543
544
545 /* Parameters are checked, the key pair has been created.  Now
546    generate the request and write it out */
547 static int
548 create_request (ctrl_t ctrl,
549                 struct para_data_s *para, ksba_const_sexp_t public,
550                 struct reqgen_ctrl_s *outctrl)
551 {
552   ksba_certreq_t cr;
553   gpg_error_t err;
554   gcry_md_hd_t md;
555   ksba_stop_reason_t stopreason;
556   int rc = 0;
557   const char *s;
558   unsigned int use;
559   int seq;
560   char *buf, *p;
561   size_t len;
562   char numbuf[30];
563
564   err = ksba_certreq_new (&cr);
565   if (err)
566     return err;
567
568   rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
569   if (rc)
570     {
571       log_error ("md_open failed: %s\n", gpg_strerror (rc));
572       goto leave;
573     }
574   if (DBG_HASHING)
575     gcry_md_start_debug (md, "cr.cri");
576
577   ksba_certreq_set_hash_function (cr, HASH_FNC, md);
578   ksba_certreq_set_writer (cr, outctrl->writer);
579   
580   err = ksba_certreq_add_subject (cr, get_parameter_value (para, pNAMEDN, 0));
581   if (err)
582     {
583       log_error ("error setting the subject's name: %s\n",
584                  gpg_strerror (err));
585       rc = err;
586       goto leave;
587     }
588
589   for (seq=0; (s = get_parameter_value (para, pNAMEEMAIL, seq)); seq++)
590     {
591       buf = xtrymalloc (strlen (s) + 3);
592       if (!buf)
593         {
594           rc = OUT_OF_CORE (errno);
595           goto leave;
596         }
597       *buf = '<';
598       strcpy (buf+1, s);
599       strcat (buf+1, ">");
600       err = ksba_certreq_add_subject (cr, buf);
601       xfree (buf);
602       if (err)
603         {
604           log_error ("error setting the subject's alternate name: %s\n",
605                      gpg_strerror (err));
606           rc = err;
607           goto leave;
608         }
609     }
610
611   for (seq=0; (s = get_parameter_value (para, pNAMEDNS, seq)); seq++)
612     {
613       len = strlen (s);
614       assert (len);
615       snprintf (numbuf, DIM(numbuf), "%u:", (unsigned int)len);
616       buf = p = xtrymalloc (11 + strlen (numbuf) + len + 3);
617       if (!buf)
618         {
619           rc = OUT_OF_CORE (errno);
620           goto leave;
621         }
622       p = stpcpy (p, "(8:dns-name");
623       p = stpcpy (p, numbuf);
624       p = stpcpy (p, s);
625       strcpy (p, ")");
626
627       err = ksba_certreq_add_subject (cr, buf);
628       xfree (buf);
629       if (err)
630         {
631           log_error ("error setting the subject's alternate name: %s\n",
632                      gpg_strerror (err));
633           rc = err;
634           goto leave;
635         }
636     }
637
638   for (seq=0; (s = get_parameter_value (para, pNAMEURI, seq)); seq++)
639     {
640       len = strlen (s);
641       assert (len);
642       snprintf (numbuf, DIM(numbuf), "%u:", (unsigned int)len);
643       buf = p = xtrymalloc (6 + strlen (numbuf) + len + 3);
644       if (!buf)
645         {
646           rc = OUT_OF_CORE (errno);
647           goto leave;
648         }
649       p = stpcpy (p, "(3:uri");
650       p = stpcpy (p, numbuf);
651       p = stpcpy (p, s);
652       strcpy (p, ")");
653
654       err = ksba_certreq_add_subject (cr, buf);
655       xfree (buf);
656       if (err)
657         {
658           log_error ("error setting the subject's alternate name: %s\n",
659                      gpg_strerror (err));
660           rc = err;
661           goto leave;
662         }
663     }
664
665
666   err = ksba_certreq_set_public_key (cr, public);
667   if (err)
668     {
669       log_error ("error setting the public key: %s\n",
670                  gpg_strerror (err));
671       rc = err;
672       goto leave;
673     }
674
675   
676   use = get_parameter_uint (para, pKEYUSAGE);
677   if (use == GCRY_PK_USAGE_SIGN)
678     {
679       /* For signing only we encode the bits:
680          KSBA_KEYUSAGE_DIGITAL_SIGNATURE
681          KSBA_KEYUSAGE_NON_REPUDIATION */
682       err = ksba_certreq_add_extension (cr, oidstr_keyUsage, 1, 
683                                         "\x03\x02\x06\xC0", 4);
684     }
685   else if (use == GCRY_PK_USAGE_ENCR)
686     {
687       /* For encrypt only we encode the bits:
688          KSBA_KEYUSAGE_KEY_ENCIPHERMENT
689          KSBA_KEYUSAGE_DATA_ENCIPHERMENT */
690       err = ksba_certreq_add_extension (cr, oidstr_keyUsage, 1, 
691                                         "\x03\x02\x04\x30", 4);
692     }
693   else
694     err = 0; /* Both or none given: don't request one. */
695   if (err)
696     {
697       log_error ("error setting the key usage: %s\n",
698                  gpg_strerror (err));
699       rc = err;
700       goto leave;
701     }
702
703                
704   do
705     {
706       err = ksba_certreq_build (cr, &stopreason);
707       if (err)
708         {
709           log_error ("ksba_certreq_build failed: %s\n", gpg_strerror (err));
710           rc = err;
711           goto leave;
712         }
713       if (stopreason == KSBA_SR_NEED_SIG)
714         {
715           gcry_sexp_t s_pkey;
716           size_t n;
717           unsigned char grip[20];
718           char hexgrip[41];
719           unsigned char *sigval;
720           size_t siglen;
721
722           n = gcry_sexp_canon_len (public, 0, NULL, NULL);
723           if (!n)
724             {
725               log_error ("libksba did not return a proper S-Exp\n");
726               err = gpg_error (GPG_ERR_BUG);
727               goto leave;
728             }
729           rc = gcry_sexp_sscan (&s_pkey, NULL, (const char*)public, n);
730           if (rc)
731             {
732               log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
733               goto leave;
734             }
735           if ( !gcry_pk_get_keygrip (s_pkey, grip) )
736             {
737               rc = gpg_error (GPG_ERR_GENERAL);
738               log_error ("can't figure out the keygrip\n");
739               gcry_sexp_release (s_pkey);
740               goto leave;
741             }
742           gcry_sexp_release (s_pkey);
743           for (n=0; n < 20; n++)
744             sprintf (hexgrip+n*2, "%02X", grip[n]);
745
746           rc = gpgsm_agent_pksign (ctrl, hexgrip, NULL,
747                                    gcry_md_read(md, GCRY_MD_SHA1), 
748                                    gcry_md_get_algo_dlen (GCRY_MD_SHA1),
749                                    GCRY_MD_SHA1,
750                                    &sigval, &siglen);
751           if (rc)
752             {
753               log_error ("signing failed: %s\n", gpg_strerror (rc));
754               goto leave;
755             }
756           
757           err = ksba_certreq_set_sig_val (cr, sigval);
758           xfree (sigval);
759           if (err)
760             {
761               log_error ("failed to store the sig_val: %s\n",
762                          gpg_strerror (err));
763               rc = err;
764               goto leave;
765             }
766         }
767     }
768   while (stopreason != KSBA_SR_READY);   
769   
770
771  leave:
772   gcry_md_close (md);
773   ksba_certreq_release (cr);
774   return rc;  
775 }
776
777
778 \f
779 /* Create a new key by reading the parameters from in_fd.  Multiple
780    keys may be created */
781 int
782 gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp)
783 {
784   int rc;
785   FILE *in_fp;
786   Base64Context b64writer = NULL;
787   ksba_writer_t writer;
788
789   in_fp = fdopen (dup (in_fd), "rb");
790   if (!in_fp)
791     {
792       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
793       log_error ("fdopen() failed: %s\n", strerror (errno));
794       return tmperr;
795     }
796
797   ctrl->pem_name = "CERTIFICATE REQUEST";
798   rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
799   if (rc)
800     {
801       log_error ("can't create writer: %s\n", gpg_strerror (rc));
802       goto leave;
803     }
804
805   rc = read_parameters (ctrl, in_fp, writer);
806   if (rc)
807     {
808       log_error ("error creating certificate request: %s\n",
809                  gpg_strerror (rc));
810       goto leave;
811     }
812
813   rc = gpgsm_finish_writer (b64writer);
814   if (rc) 
815     {
816       log_error ("write failed: %s\n", gpg_strerror (rc));
817       goto leave;
818     }
819
820   gpgsm_status (ctrl, STATUS_KEY_CREATED, "P");
821   log_info ("certificate request created\n");
822
823  leave:
824   gpgsm_destroy_writer (b64writer);
825   fclose (in_fp);
826   return rc;
827 }
828