* call-dirmngr.c (inq_certificate): Changed for new interface semantic.
[gnupg.git] / sm / certreqgen.c
1 /* certreqgen.c - Generate a key and a certification request
2  *      Copyright (C) 2002 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 ist the email address
75
76 Here is an example:
77 $ cat >foo <<EOF
78 %echo Generating a standard key
79 Key-Type: RSA
80 Key-Length: 1024
81 Name-DN: CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE
82 Name-Email: joe@foo.bar
83 # Do a commit here, so that we can later print "done" :-)
84 %commit
85 %echo done
86 EOF
87 */
88
89
90 #include <config.h>
91 #include <stdio.h>
92 #include <stdlib.h>
93 #include <string.h>
94 #include <errno.h>
95 #include <unistd.h> 
96 #include <time.h>
97 #include <assert.h>
98
99 #include <gcrypt.h>
100 #include <ksba.h>
101
102 #include "gpgsm.h"
103 #include "keydb.h"
104 #include "i18n.h"
105
106
107 enum para_name {
108   pKEYTYPE,
109   pKEYLENGTH,
110   pKEYUSAGE,
111   pNAMEDN,
112   pNAMEEMAIL
113 };
114
115 struct para_data_s {
116   struct para_data_s *next;
117   int lnr;
118   enum para_name key;
119   union {
120     unsigned int usage; 
121     char value[1];
122   } u;
123 };
124
125 struct reqgen_ctrl_s {
126   int lnr;
127   int dryrun;
128   KsbaWriter writer;
129 };
130
131
132 static int proc_parameters (struct para_data_s *para,
133                             struct reqgen_ctrl_s *outctrl);
134 static int create_request (struct para_data_s *para,
135                            KsbaConstSexp public,
136                            struct reqgen_ctrl_s *outctrl);
137
138
139 \f
140 static void
141 release_parameter_list (struct para_data_s *r)
142 {
143   struct para_data_s *r2;
144   
145   for (; r ; r = r2)
146     {
147       r2 = r->next;
148       xfree(r);
149     }
150 }
151
152 static struct para_data_s *
153 get_parameter (struct para_data_s *para, enum para_name key)
154 {
155   struct para_data_s *r;
156   
157   for (r = para; r && r->key != key; r = r->next)
158     ;
159   return r;
160 }
161
162 static const char *
163 get_parameter_value (struct para_data_s *para, enum para_name key)
164 {
165   struct para_data_s *r = get_parameter (para, key);
166   return (r && *r->u.value)? r->u.value : NULL;
167 }
168
169 static int
170 get_parameter_algo (struct para_data_s *para, enum para_name key)
171 {
172   struct para_data_s *r = get_parameter (para, key);
173   if (!r)
174     return -1;
175   if (digitp (r->u.value))
176     return atoi( r->u.value );
177   return gcry_pk_map_name (r->u.value); 
178 }
179
180 /* parse the usage parameter.  Returns 0 on success.  Note that we
181    only care about sign and encrypt and don't (yet) allow all the
182    other X.509 usage to be specified; instead we will use a fixed
183    mapping to the X.509 usage flags */
184 static int
185 parse_parameter_usage (struct para_data_s *para, enum para_name key)
186 {
187   struct para_data_s *r = get_parameter (para, key);
188   char *p, *pn;
189   unsigned int use;
190   
191   if (!r)
192     return 0; /* none (this is an optional parameter)*/
193     
194   use = 0;
195   pn = r->u.value;
196   while ( (p = strsep (&pn, " \t,")) )
197     {
198       if (!*p)
199         ;
200       else if ( !ascii_strcasecmp (p, "sign") )
201         use |= GCRY_PK_USAGE_SIGN;
202       else if ( !ascii_strcasecmp (p, "encrypt") )
203         use |= GCRY_PK_USAGE_ENCR;
204       else
205         {
206           log_error ("line %d: invalid usage list\n", r->lnr);
207           return -1; /* error */
208         }
209     }
210   r->u.usage = use;
211   return 0;
212 }
213
214
215 static unsigned int
216 get_parameter_uint (struct para_data_s *para, enum para_name key)
217 {
218   struct para_data_s *r = get_parameter (para, key);
219
220   if (!r)
221     return 0;
222
223   return (unsigned int)strtoul (r->u.value, NULL, 10);
224 }
225
226
227
228 /* Read the certificate generation parameters from FP and genereate
229    (all) certificate requests.  */
230 static int
231 read_parameters (FILE *fp, KsbaWriter writer)
232 {
233   static struct {
234     const char *name;
235     enum para_name key;
236   } keywords[] = {
237     { "Key-Type",       pKEYTYPE},
238     { "Key-Length",     pKEYLENGTH },
239     { "Key-Usage",      pKEYUSAGE },
240     { "Name-DN",        pNAMEDN },
241     { "Name-Email",     pNAMEEMAIL },
242     { NULL, 0 }
243   };
244   char line[1024], *p;
245   const char *err = NULL;
246   struct para_data_s *para, *r;
247   int i;
248   struct reqgen_ctrl_s outctrl;
249
250   memset (&outctrl, 0, sizeof (outctrl));
251   outctrl.writer = writer;
252
253   err = NULL;
254   para = NULL;
255   while (fgets (line, DIM(line)-1, fp) )
256     {
257       char *keyword, *value;
258
259       outctrl.lnr++;
260       if (*line && line[strlen(line)-1] != '\n')
261         {
262           err = "line too long";
263           break;
264         }
265       for (p=line; spacep (p); p++)
266         ;
267       if (!*p || *p == '#')
268         continue;
269
270       keyword = p;
271       if (*keyword == '%')
272         {
273           for (; !spacep (p); p++)
274             ;
275           if (*p)
276             *p++ = 0;
277           for (; spacep (p); p++)
278             ;
279           value = p;
280           trim_trailing_spaces (value);
281
282           if (!ascii_strcasecmp (keyword, "%echo"))
283             log_info ("%s\n", value);
284           else if (!ascii_strcasecmp (keyword, "%dry-run"))
285             outctrl.dryrun = 1;
286           else if (!ascii_strcasecmp( keyword, "%commit"))
287             {
288               proc_parameters (para, &outctrl);
289               /*FIXME: what about error handling */
290               release_parameter_list (para);
291               para = NULL;
292             }
293           else
294             log_info ("skipping control `%s' (%s)\n", keyword, value);
295
296           continue;
297         }
298
299
300       if (!(p = strchr (p, ':')) || p == keyword)
301         {
302           err = "missing colon";
303           break;
304         }
305       if (*p)
306         *p++ = 0;
307       for (; spacep (p); p++)
308         ;
309       if (!*p)
310         {
311           err = "missing argument";
312           break;
313         }
314       value = p;
315       trim_trailing_spaces (value);
316
317       for (i=0; (keywords[i].name
318                  && ascii_strcasecmp (keywords[i].name, keyword)); i++)
319         ;
320       if (!keywords[i].name)
321         {
322           err = "unknown keyword";
323           break;
324         }
325       if (keywords[i].key != pKEYTYPE && !para)
326         {
327           err = "parameter block does not start with \"Key-Type\"";
328           break;
329         }
330
331       if (keywords[i].key == pKEYTYPE && para)
332         {
333           proc_parameters (para, &outctrl);
334           release_parameter_list (para);
335           para = NULL;
336         }
337       else
338         {
339           for (r = para; r && r->key != keywords[i].key; r = r->next)
340             ;
341           if (r)
342             {
343               err = "duplicate keyword";
344               break;
345             }
346         }
347
348       r = xtrycalloc (1, sizeof *r + strlen( value ));
349       if (!r)
350         {
351           err = "out of core";
352           break;
353         }
354       r->lnr = outctrl.lnr;
355       r->key = keywords[i].key;
356       strcpy (r->u.value, value);
357       r->next = para;
358       para = r;
359     }
360
361   if (err)
362     log_error ("line %d: %s\n", outctrl.lnr, err);
363   else if (ferror(fp))
364     log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) );
365   else if (para)
366     {
367       proc_parameters (para, &outctrl);
368       /*FIXME: what about error handling */
369     }
370
371   release_parameter_list (para);
372   return 0;
373 }
374
375 /* check whether there are invalid characters in the email address S */
376 static int
377 has_invalid_email_chars (const char *s)
378 {
379   int at_seen=0;
380   static char valid_chars[] = "01234567890_-."
381                               "abcdefghijklmnopqrstuvwxyz"
382                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
383   for (; *s; s++)
384     {
385       if (*s & 0x80)
386         return 1;
387       if (*s == '@')
388         at_seen++;
389       else if (!at_seen && !( !!strchr (valid_chars, *s) || *s == '+'))
390         return 1;
391       else if (at_seen && !strchr (valid_chars, *s))
392         return 1;
393     }
394   return at_seen != 1;
395 }
396
397
398 /* Check that all required parameters are given and perform the action */
399 static int
400 proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl)
401 {
402   struct para_data_s *r;
403   const char *s;
404   int i;
405   unsigned int nbits;
406   char numbuf[20];
407   unsigned char keyparms[100];
408   int rc;
409   KsbaSexp public;
410   
411   /* check that we have all required parameters */
412   assert (get_parameter (para, pKEYTYPE));
413
414   /* We can only use RSA for now.  There is a with pkcs-10 on how to
415      use ElGamal becuase it is expected that a PK algorithm can always
416      be used for signing. */
417   i = get_parameter_algo (para, pKEYTYPE);
418   if (i < 1 || i != GCRY_PK_RSA )
419     {
420       r = get_parameter (para, pKEYTYPE);
421       log_error ("line %d: invalid algorithm\n", r->lnr);
422       return GNUPG_Invalid_Parameter;
423     }
424   
425   /* check the keylength */
426   if (!get_parameter (para, pKEYLENGTH))
427     nbits = 1024;
428   else
429     nbits = get_parameter_uint (para, pKEYLENGTH);
430   if (nbits < 512 || nbits > 4096)
431     {
432       r = get_parameter (para, pKEYTYPE);
433       log_error ("line %d: invalid key length %u (valid are 512 to 4096)\n",
434                  r->lnr, nbits);
435       return GNUPG_Invalid_Parameter;
436     }
437     
438   /* check the usage */
439   if (parse_parameter_usage (para, pKEYUSAGE))
440     return GNUPG_Invalid_Parameter;
441
442   /* check that there is a subject name and that this DN fits our
443      requirements */
444   if (!(s=get_parameter_value (para, pNAMEDN)))
445     {
446       r = get_parameter (para, pKEYTYPE);
447       log_error ("line %d: no subject name given\n", r->lnr);
448       return GNUPG_Invalid_Parameter;
449     }
450   /* fixme check s */
451
452   /* check that the optional email address is okay */
453   if ((s=get_parameter_value (para, pNAMEEMAIL)))
454     { 
455       if (has_invalid_email_chars (s)
456           || *s == '@'
457           || s[strlen(s)-1] == '@'
458           || s[strlen(s)-1] == '.'
459           || strstr(s, ".."))
460         {
461           r = get_parameter (para, pKEYTYPE);
462           log_error ("line %d: not a valid email address\n", r->lnr);
463           return GNUPG_Invalid_Parameter;
464         }
465     }
466
467   sprintf (numbuf, "%u", nbits);
468   snprintf (keyparms, DIM (keyparms)-1, 
469             "(6:genkey(3:rsa(5:nbits%d:%s)))", strlen (numbuf), numbuf);
470   rc = gpgsm_agent_genkey (keyparms, &public);
471   if (rc)
472     {
473       r = get_parameter (para, pKEYTYPE);
474       log_error ("line %d: key generation failed: %s\n",
475                  r->lnr, gnupg_strerror (rc));
476       return rc;
477     }
478
479   rc = create_request (para, public, outctrl);
480   xfree (public);
481
482   return rc;
483 }
484
485
486 /* Parameters are checked, the key pair has been created.  Now
487    generate the request and write it out */
488 static int
489 create_request (struct para_data_s *para, KsbaConstSexp public,
490                 struct reqgen_ctrl_s *outctrl)
491 {
492   KsbaCertreq cr;
493   KsbaError err;
494   GCRY_MD_HD md;
495   KsbaStopReason stopreason;
496   int rc = 0;
497
498   cr = ksba_certreq_new ();
499   if (!cr)
500     return seterr (Out_Of_Core);
501
502   md = gcry_md_open (GCRY_MD_SHA1, 0);
503   if (!md)
504     {
505       log_error ("md_open failed: %s\n", gcry_strerror (-1));
506       rc = map_gcry_err (gcry_errno ());
507       goto leave;
508     }
509   if (DBG_HASHING)
510     gcry_md_start_debug (md, "cr.cri");
511
512   ksba_certreq_set_hash_function (cr, HASH_FNC, md);
513   ksba_certreq_set_writer (cr, outctrl->writer);
514   
515   err = ksba_certreq_set_subject (cr, get_parameter_value (para, pNAMEDN));
516   if (err)
517     {
518       log_error ("error setting the subject's name: %s\n",
519                  ksba_strerror (err));
520       rc = map_ksba_err (err);
521       goto leave;
522     }
523
524   err = ksba_certreq_set_public_key (cr, public);
525   if (err)
526     {
527       log_error ("error setting the public key: %s\n",
528                  ksba_strerror (err));
529       rc = map_ksba_err (err);
530       goto leave;
531     }
532                
533   do
534     {
535       err = ksba_certreq_build (cr, &stopreason);
536       if (err)
537         {
538           log_error ("ksba_certreq_build failed: %s\n", ksba_strerror (err));
539           rc = map_ksba_err (err);
540           goto leave;
541         }
542       if (stopreason == KSBA_SR_NEED_SIG)
543         {
544           GCRY_SEXP s_pkey;
545           size_t n;
546           unsigned char grip[20], hexgrip[41];
547           char *sigval;
548           size_t siglen;
549
550           n = gcry_sexp_canon_len (public, 0, NULL, NULL);
551           if (!n)
552             {
553               log_error ("libksba did not return a proper S-Exp\n");
554               err = GNUPG_Bug;
555               goto leave;
556             }
557           rc = gcry_sexp_sscan (&s_pkey, NULL, public, n);
558           if (rc)
559             {
560               log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
561               rc = map_gcry_err (rc);
562               goto leave;
563             }
564           if ( !gcry_pk_get_keygrip (s_pkey, grip) )
565             {
566               rc = seterr (General_Error);
567               log_error ("can't figure out the keygrip\n");
568               gcry_sexp_release (s_pkey);
569               goto leave;
570             }
571           gcry_sexp_release (s_pkey);
572           for (n=0; n < 20; n++)
573             sprintf (hexgrip+n*2, "%02X", grip[n]);
574
575           rc = gpgsm_agent_pksign (hexgrip,
576                                    gcry_md_read(md, GCRY_MD_SHA1), 
577                                    gcry_md_get_algo_dlen (GCRY_MD_SHA1),
578                                    GCRY_MD_SHA1,
579                                    &sigval, &siglen);
580           if (rc)
581             {
582               log_error ("signing failed: %s\n", gnupg_strerror (rc));
583               goto leave;
584             }
585           
586           err = ksba_certreq_set_sig_val (cr, sigval);
587           xfree (sigval);
588           if (err)
589             {
590               log_error ("failed to store the sig_val: %s\n",
591                          ksba_strerror (err));
592               rc = map_ksba_err (err);
593               goto leave;
594             }
595         }
596     }
597   while (stopreason != KSBA_SR_READY);   
598   
599
600  leave:
601   gcry_md_close (md);
602   ksba_certreq_release (cr);
603   return rc;  
604 }
605
606
607 \f
608 /* Create a new key by reading the parameters from in_fd.  Multiple
609    keys may be created */
610 int
611 gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp)
612 {
613   int rc;
614   FILE *in_fp;
615   Base64Context b64writer = NULL;
616   KsbaWriter writer;
617
618   in_fp = fdopen (dup (in_fd), "rb");
619   if (!in_fp)
620     {
621       log_error ("fdopen() failed: %s\n", strerror (errno));
622       return seterr (IO_Error);
623     }
624
625   ctrl->pem_name = "NEW CERTIFICATE REQUEST";
626   rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
627   if (rc)
628     {
629       log_error ("can't create writer: %s\n", gnupg_strerror (rc));
630       goto leave;
631     }
632
633   rc = read_parameters (in_fp, writer);
634   if (rc)
635     goto leave;
636
637   rc = gpgsm_finish_writer (b64writer);
638   if (rc) 
639     {
640       log_error ("write failed: %s\n", gnupg_strerror (rc));
641       goto leave;
642     }
643
644   log_info ("certificate request created\n");
645
646  leave:
647   gpgsm_destroy_writer (b64writer);
648   fclose (in_fp);
649   return rc;
650 }
651