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