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