LCOV - code coverage report
Current view: top level - sm - certreqgen.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 641 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /* certreqgen.c - Generate a key and a certification [request]
       2             :  * Copyright (C) 2002, 2003, 2005, 2007, 2010,
       3             :  *               2011 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : /*
      22             :    The format of the parameter file is described in the manual under
      23             :    "Unattended Usage".
      24             : 
      25             :    Here is an example:
      26             :      $ cat >foo <<EOF
      27             :      %echo Generating a standard key
      28             :      Key-Type: RSA
      29             :      Key-Length: 2048
      30             :      Name-DN: CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Ddorf,C=DE
      31             :      Name-Email: joe@foo.bar
      32             :      # Do a commit here, so that we can later print a "done"
      33             :      %commit
      34             :      %echo done
      35             :      EOF
      36             : 
      37             :    This parameter file was used to create the STEED CA:
      38             :      Key-Type: RSA
      39             :      Key-Length: 1024
      40             :      Key-Grip: 68A638998DFABAC510EA645CE34F9686B2EDF7EA
      41             :      Key-Usage: cert
      42             :      Serial: 1
      43             :      Name-DN: CN=The STEED Self-Signing Nonthority
      44             :      Not-Before: 2011-11-11
      45             :      Not-After: 2106-02-06
      46             :      Subject-Key-Id: 68A638998DFABAC510EA645CE34F9686B2EDF7EA
      47             :      Extension: 2.5.29.19 c 30060101ff020101
      48             :      Extension: 1.3.6.1.4.1.11591.2.2.2 n 0101ff
      49             :      Signing-Key: 68A638998DFABAC510EA645CE34F9686B2EDF7EA
      50             :      %commit
      51             : 
      52             : */
      53             : 
      54             : 
      55             : #include <config.h>
      56             : #include <stdio.h>
      57             : #include <stdlib.h>
      58             : #include <string.h>
      59             : #include <errno.h>
      60             : #include <unistd.h>
      61             : #include <time.h>
      62             : #include <assert.h>
      63             : 
      64             : #include "gpgsm.h"
      65             : #include <gcrypt.h>
      66             : #include <ksba.h>
      67             : 
      68             : #include "keydb.h"
      69             : #include "i18n.h"
      70             : 
      71             : 
      72             : enum para_name
      73             :   {
      74             :     pKEYTYPE,
      75             :     pKEYLENGTH,
      76             :     pKEYGRIP,
      77             :     pKEYUSAGE,
      78             :     pNAMEDN,
      79             :     pNAMEEMAIL,
      80             :     pNAMEDNS,
      81             :     pNAMEURI,
      82             :     pSERIAL,
      83             :     pISSUERDN,
      84             :     pNOTBEFORE,
      85             :     pNOTAFTER,
      86             :     pSIGNINGKEY,
      87             :     pHASHALGO,
      88             :     pAUTHKEYID,
      89             :     pSUBJKEYID,
      90             :     pEXTENSION
      91             :   };
      92             : 
      93             : struct para_data_s
      94             : {
      95             :   struct para_data_s *next;
      96             :   int lnr;
      97             :   enum para_name key;
      98             :   union {
      99             :     unsigned int usage;
     100             :     char value[1];
     101             :   } u;
     102             : };
     103             : 
     104             : struct reqgen_ctrl_s
     105             : {
     106             :   int lnr;
     107             :   int dryrun;
     108             : };
     109             : 
     110             : 
     111             : static const char oidstr_authorityKeyIdentifier[] = "2.5.29.35";
     112             : static const char oidstr_subjectKeyIdentifier[] = "2.5.29.14";
     113             : static const char oidstr_keyUsage[] = "2.5.29.15";
     114             : static const char oidstr_basicConstraints[] = "2.5.29.19";
     115             : static const char oidstr_standaloneCertificate[] = "1.3.6.1.4.1.11591.2.2.1";
     116             : 
     117             : 
     118             : static int proc_parameters (ctrl_t ctrl,
     119             :                             struct para_data_s *para,
     120             :                             estream_t out_fp,
     121             :                             struct reqgen_ctrl_s *outctrl);
     122             : static int create_request (ctrl_t ctrl,
     123             :                            struct para_data_s *para,
     124             :                            const char *carddirect,
     125             :                            ksba_const_sexp_t public,
     126             :                            ksba_const_sexp_t sigkey,
     127             :                            ksba_writer_t writer);
     128             : 
     129             : 
     130             : 
     131             : static void
     132           0 : release_parameter_list (struct para_data_s *r)
     133             : {
     134             :   struct para_data_s *r2;
     135             : 
     136           0 :   for (; r ; r = r2)
     137             :     {
     138           0 :       r2 = r->next;
     139           0 :       xfree(r);
     140             :     }
     141           0 : }
     142             : 
     143             : static struct para_data_s *
     144           0 : get_parameter (struct para_data_s *para, enum para_name key, int seq)
     145             : {
     146             :   struct para_data_s *r;
     147             : 
     148           0 :   for (r = para; r ; r = r->next)
     149           0 :     if ( r->key == key && !seq--)
     150           0 :       return r;
     151           0 :   return NULL;
     152             : }
     153             : 
     154             : static const char *
     155           0 : get_parameter_value (struct para_data_s *para, enum para_name key, int seq)
     156             : {
     157           0 :   struct para_data_s *r = get_parameter (para, key, seq);
     158           0 :   return (r && *r->u.value)? r->u.value : NULL;
     159             : }
     160             : 
     161             : static int
     162           0 : get_parameter_algo (struct para_data_s *para, enum para_name key)
     163             : {
     164           0 :   struct para_data_s *r = get_parameter (para, key, 0);
     165           0 :   if (!r)
     166           0 :     return -1;
     167           0 :   if (digitp (r->u.value))
     168           0 :     return atoi( r->u.value );
     169           0 :   return gcry_pk_map_name (r->u.value);
     170             : }
     171             : 
     172             : /* Parse the usage parameter.  Returns 0 on success.  Note that we
     173             :    only care about sign and encrypt and don't (yet) allow all the
     174             :    other X.509 usage to be specified; instead we will use a fixed
     175             :    mapping to the X.509 usage flags. */
     176             : static int
     177           0 : parse_parameter_usage (struct para_data_s *para, enum para_name key)
     178             : {
     179           0 :   struct para_data_s *r = get_parameter (para, key, 0);
     180             :   char *p, *pn;
     181             :   unsigned int use;
     182             : 
     183           0 :   if (!r)
     184           0 :     return 0; /* none (this is an optional parameter)*/
     185             : 
     186           0 :   use = 0;
     187           0 :   pn = r->u.value;
     188           0 :   while ( (p = strsep (&pn, " \t,")) )
     189             :     {
     190           0 :       if (!*p)
     191             :         ;
     192           0 :       else if ( !ascii_strcasecmp (p, "sign") )
     193           0 :         use |= GCRY_PK_USAGE_SIGN;
     194           0 :       else if ( !ascii_strcasecmp (p, "encrypt")
     195           0 :                 || !ascii_strcasecmp (p, "encr") )
     196           0 :         use |= GCRY_PK_USAGE_ENCR;
     197           0 :       else if ( !ascii_strcasecmp (p, "cert") )
     198           0 :         use |= GCRY_PK_USAGE_CERT;
     199             :       else
     200             :         {
     201           0 :           log_error ("line %d: invalid usage list\n", r->lnr);
     202           0 :           return -1; /* error */
     203             :         }
     204             :     }
     205           0 :   r->u.usage = use;
     206           0 :   return 0;
     207             : }
     208             : 
     209             : 
     210             : static unsigned int
     211           0 : get_parameter_uint (struct para_data_s *para, enum para_name key)
     212             : {
     213           0 :   struct para_data_s *r = get_parameter (para, key, 0);
     214             : 
     215           0 :   if (!r)
     216           0 :     return 0;
     217             : 
     218           0 :   if (r->key == pKEYUSAGE)
     219           0 :     return r->u.usage;
     220             : 
     221           0 :   return (unsigned int)strtoul (r->u.value, NULL, 10);
     222             : }
     223             : 
     224             : 
     225             : 
     226             : /* Read the certificate generation parameters from FP and generate
     227             :    (all) certificate requests.  */
     228             : static int
     229           0 : read_parameters (ctrl_t ctrl, estream_t fp, estream_t out_fp)
     230             : {
     231             :   static struct {
     232             :     const char *name;
     233             :     enum para_name key;
     234             :     int allow_dups;
     235             :   } keywords[] = {
     236             :     { "Key-Type",       pKEYTYPE},
     237             :     { "Key-Length",     pKEYLENGTH },
     238             :     { "Key-Grip",       pKEYGRIP },
     239             :     { "Key-Usage",      pKEYUSAGE },
     240             :     { "Name-DN",        pNAMEDN },
     241             :     { "Name-Email",     pNAMEEMAIL, 1 },
     242             :     { "Name-DNS",       pNAMEDNS, 1 },
     243             :     { "Name-URI",       pNAMEURI, 1 },
     244             :     { "Serial",         pSERIAL },
     245             :     { "Issuer-DN",      pISSUERDN },
     246             :     { "Creation-Date",  pNOTBEFORE },
     247             :     { "Not-Before",     pNOTBEFORE },
     248             :     { "Expire-Date",    pNOTAFTER },
     249             :     { "Not-After",      pNOTAFTER },
     250             :     { "Signing-Key",    pSIGNINGKEY },
     251             :     { "Hash-Algo",      pHASHALGO },
     252             :     { "Authority-Key-Id", pAUTHKEYID },
     253             :     { "Subject-Key-Id", pSUBJKEYID },
     254             :     { "Extension",      pEXTENSION, 1 },
     255             :     { NULL, 0 }
     256             :   };
     257             :   char line[1024], *p;
     258           0 :   const char *err = NULL;
     259             :   struct para_data_s *para, *r;
     260           0 :   int i, rc = 0, any = 0;
     261             :   struct reqgen_ctrl_s outctrl;
     262             : 
     263           0 :   memset (&outctrl, 0, sizeof (outctrl));
     264             : 
     265           0 :   err = NULL;
     266           0 :   para = NULL;
     267           0 :   while (es_fgets (line, DIM(line)-1, fp) )
     268             :     {
     269             :       char *keyword, *value;
     270             : 
     271           0 :       outctrl.lnr++;
     272           0 :       if (*line && line[strlen(line)-1] != '\n')
     273             :         {
     274           0 :           err = "line too long";
     275           0 :           break;
     276             :         }
     277           0 :       for (p=line; spacep (p); p++)
     278             :         ;
     279           0 :       if (!*p || *p == '#')
     280           0 :         continue;
     281             : 
     282           0 :       keyword = p;
     283           0 :       if (*keyword == '%')
     284             :         {
     285           0 :           for (; *p && !ascii_isspace (*p); p++)
     286             :             ;
     287           0 :           if (*p)
     288           0 :             *p++ = 0;
     289           0 :           for (; ascii_isspace (*p); p++)
     290             :             ;
     291           0 :           value = p;
     292           0 :           trim_trailing_spaces (value);
     293             : 
     294           0 :           if (!ascii_strcasecmp (keyword, "%echo"))
     295           0 :             log_info ("%s\n", value);
     296           0 :           else if (!ascii_strcasecmp (keyword, "%dry-run"))
     297           0 :             outctrl.dryrun = 1;
     298           0 :           else if (!ascii_strcasecmp( keyword, "%commit"))
     299             :             {
     300           0 :               rc = proc_parameters (ctrl, para, out_fp, &outctrl);
     301           0 :               if (rc)
     302           0 :                 goto leave;
     303           0 :               any = 1;
     304           0 :               release_parameter_list (para);
     305           0 :               para = NULL;
     306             :             }
     307             :           else
     308           0 :             log_info ("skipping control '%s' (%s)\n", keyword, value);
     309             : 
     310           0 :           continue;
     311             :         }
     312             : 
     313             : 
     314           0 :       if (!(p = strchr (p, ':')) || p == keyword)
     315             :         {
     316           0 :           err = "missing colon";
     317           0 :           break;
     318             :         }
     319           0 :       if (*p)
     320           0 :         *p++ = 0;
     321           0 :       for (; spacep (p); p++)
     322             :         ;
     323           0 :       if (!*p)
     324             :         {
     325           0 :           err = "missing argument";
     326           0 :           break;
     327             :         }
     328           0 :       value = p;
     329           0 :       trim_trailing_spaces (value);
     330             : 
     331           0 :       for (i=0; (keywords[i].name
     332           0 :                  && ascii_strcasecmp (keywords[i].name, keyword)); i++)
     333             :         ;
     334           0 :       if (!keywords[i].name)
     335             :         {
     336           0 :           err = "unknown keyword";
     337           0 :           break;
     338             :         }
     339           0 :       if (keywords[i].key != pKEYTYPE && !para)
     340             :         {
     341           0 :           err = "parameter block does not start with \"Key-Type\"";
     342           0 :           break;
     343             :         }
     344             : 
     345           0 :       if (keywords[i].key == pKEYTYPE && para)
     346             :         {
     347           0 :           rc = proc_parameters (ctrl, para, out_fp, &outctrl);
     348           0 :           if (rc)
     349           0 :             goto leave;
     350           0 :           any = 1;
     351           0 :           release_parameter_list (para);
     352           0 :           para = NULL;
     353             :         }
     354           0 :       else if (!keywords[i].allow_dups)
     355             :         {
     356           0 :           for (r = para; r && r->key != keywords[i].key; r = r->next)
     357             :             ;
     358           0 :           if (r)
     359             :             {
     360           0 :               err = "duplicate keyword";
     361           0 :               break;
     362             :             }
     363             :         }
     364             : 
     365           0 :       r = xtrycalloc (1, sizeof *r + strlen( value ));
     366           0 :       if (!r)
     367             :         {
     368           0 :           err = "out of core";
     369           0 :           break;
     370             :         }
     371           0 :       r->lnr = outctrl.lnr;
     372           0 :       r->key = keywords[i].key;
     373           0 :       strcpy (r->u.value, value);
     374           0 :       r->next = para;
     375           0 :       para = r;
     376             :     }
     377             : 
     378           0 :   if (err)
     379             :     {
     380           0 :       log_error ("line %d: %s\n", outctrl.lnr, err);
     381           0 :       rc = gpg_error (GPG_ERR_GENERAL);
     382             :     }
     383           0 :   else if (es_ferror(fp))
     384             :     {
     385           0 :       log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) );
     386           0 :       rc = gpg_error (GPG_ERR_GENERAL);
     387             :     }
     388           0 :   else if (para)
     389             :     {
     390           0 :       rc = proc_parameters (ctrl, para, out_fp, &outctrl);
     391           0 :       if (rc)
     392           0 :         goto leave;
     393           0 :       any = 1;
     394             :     }
     395             : 
     396           0 :   if (!rc && !any)
     397           0 :     rc = gpg_error (GPG_ERR_NO_DATA);
     398             : 
     399             :  leave:
     400           0 :   release_parameter_list (para);
     401           0 :   return rc;
     402             : }
     403             : 
     404             : /* check whether there are invalid characters in the email address S */
     405             : static int
     406           0 : has_invalid_email_chars (const char *s)
     407             : {
     408           0 :   int at_seen=0;
     409             :   static char valid_chars[] = "01234567890_-."
     410             :                               "abcdefghijklmnopqrstuvwxyz"
     411             :                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     412           0 :   for (; *s; s++)
     413             :     {
     414           0 :       if (*s & 0x80)
     415           0 :         return 1;
     416           0 :       if (*s == '@')
     417           0 :         at_seen++;
     418           0 :       else if (!at_seen && !( !!strchr (valid_chars, *s) || *s == '+'))
     419           0 :         return 1;
     420           0 :       else if (at_seen && !strchr (valid_chars, *s))
     421           0 :         return 1;
     422             :     }
     423           0 :   return at_seen != 1;
     424             : }
     425             : 
     426             : 
     427             : /* Check that all required parameters are given and perform the action */
     428             : static int
     429           0 : proc_parameters (ctrl_t ctrl, struct para_data_s *para,
     430             :                  estream_t out_fp, struct reqgen_ctrl_s *outctrl)
     431             : {
     432             :   gpg_error_t err;
     433             :   struct para_data_s *r;
     434             :   const char *s, *string;
     435             :   int i;
     436             :   unsigned int nbits;
     437             :   char numbuf[20];
     438             :   unsigned char keyparms[100];
     439           0 :   int rc = 0;
     440           0 :   ksba_sexp_t public = NULL;
     441           0 :   ksba_sexp_t sigkey = NULL;
     442             :   int seq;
     443             :   size_t erroff, errlen;
     444           0 :   char *cardkeyid = NULL;
     445             : 
     446             :   /* Check that we have all required parameters; */
     447           0 :   assert (get_parameter (para, pKEYTYPE, 0));
     448             : 
     449             :   /* We can only use RSA for now.  There is a problem with pkcs-10 on
     450             :      how to use ElGamal because it is expected that a PK algorithm can
     451             :      always be used for signing. Another problem is that on-card
     452             :      generated encryption keys may not be used for signing.  */
     453           0 :   i = get_parameter_algo (para, pKEYTYPE);
     454           0 :   if (!i && (s = get_parameter_value (para, pKEYTYPE, 0)) && *s)
     455             :     {
     456             :       /* Hack to allow creation of certificates directly from a smart
     457             :          card.  For example: "Key-Type: card:OPENPGP.3".  */
     458           0 :       if (!strncmp (s, "card:", 5) && s[5])
     459           0 :         cardkeyid = xtrystrdup (s+5);
     460             :     }
     461           0 :   if ( (i < 1 || i != GCRY_PK_RSA) && !cardkeyid )
     462             :     {
     463           0 :       r = get_parameter (para, pKEYTYPE, 0);
     464           0 :       log_error (_("line %d: invalid algorithm\n"), r->lnr);
     465           0 :       return gpg_error (GPG_ERR_INV_PARAMETER);
     466             :     }
     467             : 
     468             :   /* Check the keylength.  NOTE: If you change this make sure that it
     469             :      macthes the gpgconflist item in gpgsm.c  */
     470           0 :   if (!get_parameter (para, pKEYLENGTH, 0))
     471           0 :     nbits = 2048;
     472             :   else
     473           0 :     nbits = get_parameter_uint (para, pKEYLENGTH);
     474           0 :   if ((nbits < 1024 || nbits > 4096) && !cardkeyid)
     475             :     {
     476             :       /* The BSI specs dated 2002-11-25 don't allow lengths below 1024. */
     477           0 :       r = get_parameter (para, pKEYLENGTH, 0);
     478           0 :       log_error (_("line %d: invalid key length %u (valid are %d to %d)\n"),
     479             :                  r->lnr, nbits, 1024, 4096);
     480           0 :       xfree (cardkeyid);
     481           0 :       return gpg_error (GPG_ERR_INV_PARAMETER);
     482             :     }
     483             : 
     484             :   /* Check the usage. */
     485           0 :   if (parse_parameter_usage (para, pKEYUSAGE))
     486             :     {
     487           0 :       xfree (cardkeyid);
     488           0 :       return gpg_error (GPG_ERR_INV_PARAMETER);
     489             :     }
     490             : 
     491             :   /* Check that there is a subject name and that this DN fits our
     492             :      requirements. */
     493           0 :   if (!(s=get_parameter_value (para, pNAMEDN, 0)))
     494             :     {
     495           0 :       r = get_parameter (para, pNAMEDN, 0);
     496           0 :       log_error (_("line %d: no subject name given\n"), r->lnr);
     497           0 :       xfree (cardkeyid);
     498           0 :       return gpg_error (GPG_ERR_INV_PARAMETER);
     499             :     }
     500           0 :   err = ksba_dn_teststr (s, 0, &erroff, &errlen);
     501           0 :   if (err)
     502             :     {
     503           0 :       r = get_parameter (para, pNAMEDN, 0);
     504           0 :       if (gpg_err_code (err) == GPG_ERR_UNKNOWN_NAME)
     505           0 :         log_error (_("line %d: invalid subject name label '%.*s'\n"),
     506             :                    r->lnr, (int)errlen, s+erroff);
     507             :       else
     508           0 :         log_error (_("line %d: invalid subject name '%s' at pos %d\n"),
     509             :                    r->lnr, s, (int)erroff);
     510             : 
     511           0 :       xfree (cardkeyid);
     512           0 :       return gpg_error (GPG_ERR_INV_PARAMETER);
     513             :     }
     514             : 
     515             :   /* Check that the optional email address is okay. */
     516           0 :   for (seq=0; (s=get_parameter_value (para, pNAMEEMAIL, seq)); seq++)
     517             :     {
     518           0 :       if (has_invalid_email_chars (s)
     519           0 :           || *s == '@'
     520           0 :           || s[strlen(s)-1] == '@'
     521           0 :           || s[strlen(s)-1] == '.'
     522           0 :           || strstr(s, ".."))
     523             :         {
     524           0 :           r = get_parameter (para, pNAMEEMAIL, seq);
     525           0 :           log_error (_("line %d: not a valid email address\n"), r->lnr);
     526           0 :           xfree (cardkeyid);
     527           0 :           return gpg_error (GPG_ERR_INV_PARAMETER);
     528             :         }
     529             :     }
     530             : 
     531             :   /* Check the optional serial number.  */
     532           0 :   string = get_parameter_value (para, pSERIAL, 0);
     533           0 :   if (string)
     534             :     {
     535           0 :       if (!strcmp (string, "random"))
     536             :         ; /* Okay.  */
     537             :       else
     538             :         {
     539           0 :           for (s=string, i=0; hexdigitp (s); s++, i++)
     540             :             ;
     541           0 :           if (*s)
     542             :             {
     543           0 :               r = get_parameter (para, pSERIAL, 0);
     544           0 :               log_error (_("line %d: invalid serial number\n"), r->lnr);
     545           0 :               xfree (cardkeyid);
     546           0 :               return gpg_error (GPG_ERR_INV_PARAMETER);
     547             :             }
     548             :         }
     549             :     }
     550             : 
     551             :   /* Check the optional issuer DN.  */
     552           0 :   string = get_parameter_value (para, pISSUERDN, 0);
     553           0 :   if (string)
     554             :     {
     555           0 :       err = ksba_dn_teststr (string, 0, &erroff, &errlen);
     556           0 :       if (err)
     557             :         {
     558           0 :           r = get_parameter (para, pISSUERDN, 0);
     559           0 :           if (gpg_err_code (err) == GPG_ERR_UNKNOWN_NAME)
     560           0 :             log_error (_("line %d: invalid issuer name label '%.*s'\n"),
     561             :                        r->lnr, (int)errlen, string+erroff);
     562             :           else
     563           0 :             log_error (_("line %d: invalid issuer name '%s' at pos %d\n"),
     564             :                        r->lnr, string, (int)erroff);
     565           0 :           xfree (cardkeyid);
     566           0 :           return gpg_error (GPG_ERR_INV_PARAMETER);
     567             :         }
     568             :     }
     569             : 
     570             :   /* Check the optional creation date.  */
     571           0 :   string = get_parameter_value (para, pNOTBEFORE, 0);
     572           0 :   if (string && !string2isotime (NULL, string))
     573             :     {
     574           0 :       r = get_parameter (para, pNOTBEFORE, 0);
     575           0 :       log_error (_("line %d: invalid date given\n"), r->lnr);
     576           0 :       xfree (cardkeyid);
     577           0 :       return gpg_error (GPG_ERR_INV_PARAMETER);
     578             :     }
     579             : 
     580             : 
     581             :   /* Check the optional expire date.  */
     582           0 :   string = get_parameter_value (para, pNOTAFTER, 0);
     583           0 :   if (string && !string2isotime (NULL, string))
     584             :     {
     585           0 :       r = get_parameter (para, pNOTAFTER, 0);
     586           0 :       log_error (_("line %d: invalid date given\n"), r->lnr);
     587           0 :       xfree (cardkeyid);
     588           0 :       return gpg_error (GPG_ERR_INV_PARAMETER);
     589             :     }
     590             : 
     591             :   /* Get the optional signing key.  */
     592           0 :   string = get_parameter_value (para, pSIGNINGKEY, 0);
     593           0 :   if (string)
     594             :     {
     595           0 :       rc = gpgsm_agent_readkey (ctrl, 0, string, &sigkey);
     596           0 :       if (rc)
     597             :         {
     598           0 :           r = get_parameter (para, pKEYTYPE, 0);
     599           0 :           log_error (_("line %d: error getting signing key by keygrip '%s'"
     600             :                        ": %s\n"), r->lnr, s, gpg_strerror (rc));
     601           0 :           xfree (cardkeyid);
     602           0 :           return rc;
     603             :         }
     604             :     }
     605             : 
     606             :   /* Check the optional hash-algo.  */
     607             :   {
     608             :     int mdalgo;
     609             : 
     610           0 :     string = get_parameter_value (para, pHASHALGO, 0);
     611           0 :     if (string && !((mdalgo = gcry_md_map_name (string))
     612             :                     && (mdalgo == GCRY_MD_SHA1
     613           0 :                         || mdalgo == GCRY_MD_SHA256
     614           0 :                         || mdalgo == GCRY_MD_SHA384
     615           0 :                         || mdalgo == GCRY_MD_SHA512)))
     616             :       {
     617           0 :         r = get_parameter (para, pHASHALGO, 0);
     618           0 :         log_error (_("line %d: invalid hash algorithm given\n"), r->lnr);
     619           0 :         xfree (cardkeyid);
     620           0 :         return gpg_error (GPG_ERR_INV_PARAMETER);
     621             :       }
     622             :   }
     623             : 
     624             :   /* Check the optional AuthorityKeyId.  */
     625           0 :   string = get_parameter_value (para, pAUTHKEYID, 0);
     626           0 :   if (string)
     627             :     {
     628           0 :       for (s=string, i=0; hexdigitp (s); s++, i++)
     629             :         ;
     630           0 :       if (*s || (i&1))
     631             :         {
     632           0 :           r = get_parameter (para, pAUTHKEYID, 0);
     633           0 :           log_error (_("line %d: invalid authority-key-id\n"), r->lnr);
     634           0 :           xfree (cardkeyid);
     635           0 :           return gpg_error (GPG_ERR_INV_PARAMETER);
     636             :         }
     637             :     }
     638             : 
     639             :   /* Check the optional SubjectKeyId.  */
     640           0 :   string = get_parameter_value (para, pSUBJKEYID, 0);
     641           0 :   if (string)
     642             :     {
     643           0 :       for (s=string, i=0; hexdigitp (s); s++, i++)
     644             :         ;
     645           0 :       if (*s || (i&1))
     646             :         {
     647           0 :           r = get_parameter (para, pSUBJKEYID, 0);
     648           0 :           log_error (_("line %d: invalid subject-key-id\n"), r->lnr);
     649           0 :           xfree (cardkeyid);
     650           0 :           return gpg_error (GPG_ERR_INV_PARAMETER);
     651             :         }
     652             :     }
     653             : 
     654             :   /* Check the optional extensions. */
     655           0 :   for (seq=0; (string=get_parameter_value (para, pEXTENSION, seq)); seq++)
     656             :     {
     657           0 :       int okay = 0;
     658             : 
     659           0 :       s = strpbrk (string, " \t:");
     660           0 :       if (s)
     661             :         {
     662           0 :           s++;
     663           0 :           while (spacep (s))
     664           0 :             s++;
     665           0 :           if (*s && strchr ("nNcC", *s))
     666             :             {
     667           0 :               s++;
     668           0 :               while (spacep (s))
     669           0 :                 s++;
     670           0 :               if (*s == ':')
     671           0 :                 s++;
     672           0 :               if (*s)
     673             :                 {
     674           0 :                   while (spacep (s))
     675           0 :                     s++;
     676           0 :                   for (i=0; hexdigitp (s); s++, i++)
     677             :                     ;
     678           0 :                   if (!((*s && *s != ':') || !i || (i&1)))
     679           0 :                     okay = 1;
     680             :                 }
     681             :             }
     682             :         }
     683           0 :       if (!okay)
     684             :         {
     685           0 :           r = get_parameter (para, pEXTENSION, seq);
     686           0 :           log_error (_("line %d: invalid extension syntax\n"), r->lnr);
     687           0 :           xfree (cardkeyid);
     688           0 :           return gpg_error (GPG_ERR_INV_PARAMETER);
     689             :         }
     690             :     }
     691             : 
     692             :   /* Create or retrieve the public key.  */
     693           0 :   if (cardkeyid) /* Take the key from the current smart card. */
     694             :     {
     695           0 :       rc = gpgsm_agent_readkey (ctrl, 1, cardkeyid, &public);
     696           0 :       if (rc)
     697             :         {
     698           0 :           r = get_parameter (para, pKEYTYPE, 0);
     699           0 :           log_error (_("line %d: error reading key '%s' from card: %s\n"),
     700             :                      r->lnr, cardkeyid, gpg_strerror (rc));
     701           0 :           xfree (sigkey);
     702           0 :           xfree (cardkeyid);
     703           0 :           return rc;
     704             :         }
     705             :     }
     706           0 :   else if ((s=get_parameter_value (para, pKEYGRIP, 0))) /* Use existing key.*/
     707             :     {
     708           0 :       rc = gpgsm_agent_readkey (ctrl, 0, s, &public);
     709           0 :       if (rc)
     710             :         {
     711           0 :           r = get_parameter (para, pKEYTYPE, 0);
     712           0 :           log_error (_("line %d: error getting key by keygrip '%s': %s\n"),
     713             :                      r->lnr, s, gpg_strerror (rc));
     714           0 :           xfree (sigkey);
     715           0 :           xfree (cardkeyid);
     716           0 :           return rc;
     717             :         }
     718             :     }
     719           0 :   else if (!outctrl->dryrun) /* Generate new key.  */
     720             :     {
     721           0 :       sprintf (numbuf, "%u", nbits);
     722           0 :       snprintf ((char*)keyparms, DIM (keyparms)-1,
     723             :                 "(6:genkey(3:rsa(5:nbits%d:%s)))",
     724           0 :                 (int)strlen (numbuf), numbuf);
     725           0 :       rc = gpgsm_agent_genkey (ctrl, keyparms, &public);
     726           0 :       if (rc)
     727             :         {
     728           0 :           r = get_parameter (para, pKEYTYPE, 0);
     729           0 :           log_error (_("line %d: key generation failed: %s <%s>\n"),
     730             :                      r->lnr, gpg_strerror (rc), gpg_strsource (rc));
     731           0 :           xfree (sigkey);
     732           0 :           xfree (cardkeyid);
     733           0 :           return rc;
     734             :         }
     735             :     }
     736             : 
     737             : 
     738           0 :   if (!outctrl->dryrun)
     739             :     {
     740           0 :       Base64Context b64writer = NULL;
     741             :       ksba_writer_t writer;
     742             :       int create_cert ;
     743             : 
     744           0 :       create_cert = !!get_parameter_value (para, pSERIAL, 0);
     745             : 
     746           0 :       ctrl->pem_name = create_cert? "CERTIFICATE" : "CERTIFICATE REQUEST";
     747           0 :       rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
     748           0 :       if (rc)
     749           0 :         log_error ("can't create writer: %s\n", gpg_strerror (rc));
     750             :       else
     751             :         {
     752           0 :           rc = create_request (ctrl, para, cardkeyid, public, sigkey, writer);
     753           0 :           if (!rc)
     754             :             {
     755           0 :               rc = gpgsm_finish_writer (b64writer);
     756           0 :               if (rc)
     757           0 :                 log_error ("write failed: %s\n", gpg_strerror (rc));
     758             :               else
     759             :                 {
     760           0 :                   gpgsm_status (ctrl, STATUS_KEY_CREATED, "P");
     761           0 :                   log_info ("certificate%s created\n",
     762             :                             create_cert?"":" request");
     763             :                 }
     764             :             }
     765           0 :           gpgsm_destroy_writer (b64writer);
     766             :         }
     767             :     }
     768             : 
     769           0 :   xfree (sigkey);
     770           0 :   xfree (public);
     771           0 :   xfree (cardkeyid);
     772             : 
     773           0 :   return rc;
     774             : }
     775             : 
     776             : 
     777             : /* Parameters are checked, the key pair has been created.  Now
     778             :    generate the request and write it out */
     779             : static int
     780           0 : create_request (ctrl_t ctrl,
     781             :                 struct para_data_s *para,
     782             :                 const char *carddirect,
     783             :                 ksba_const_sexp_t public,
     784             :                 ksba_const_sexp_t sigkey,
     785             :                 ksba_writer_t writer)
     786             : {
     787             :   ksba_certreq_t cr;
     788             :   gpg_error_t err;
     789             :   gcry_md_hd_t md;
     790             :   ksba_stop_reason_t stopreason;
     791           0 :   int rc = 0;
     792             :   const char *s, *string;
     793             :   unsigned int use;
     794             :   int seq;
     795             :   char *buf, *p;
     796             :   size_t len;
     797             :   char numbuf[30];
     798             :   ksba_isotime_t atime;
     799           0 :   int certmode = 0;
     800             :   int mdalgo;
     801             : 
     802           0 :   err = ksba_certreq_new (&cr);
     803           0 :   if (err)
     804           0 :     return err;
     805             : 
     806           0 :   string = get_parameter_value (para, pHASHALGO, 0);
     807           0 :   if (string)
     808           0 :     mdalgo = gcry_md_map_name (string);
     809             :   else
     810           0 :     mdalgo = GCRY_MD_SHA256;
     811           0 :   rc = gcry_md_open (&md, mdalgo, 0);
     812           0 :   if (rc)
     813             :     {
     814           0 :       log_error ("md_open failed: %s\n", gpg_strerror (rc));
     815           0 :       goto leave;
     816             :     }
     817           0 :   if (DBG_HASHING)
     818           0 :     gcry_md_debug (md, "cr.cri");
     819             : 
     820           0 :   ksba_certreq_set_hash_function (cr, HASH_FNC, md);
     821           0 :   ksba_certreq_set_writer (cr, writer);
     822             : 
     823           0 :   err = ksba_certreq_add_subject (cr, get_parameter_value (para, pNAMEDN, 0));
     824           0 :   if (err)
     825             :     {
     826           0 :       log_error ("error setting the subject's name: %s\n",
     827             :                  gpg_strerror (err));
     828           0 :       rc = err;
     829           0 :       goto leave;
     830             :     }
     831             : 
     832           0 :   for (seq=0; (s = get_parameter_value (para, pNAMEEMAIL, seq)); seq++)
     833             :     {
     834           0 :       buf = xtrymalloc (strlen (s) + 3);
     835           0 :       if (!buf)
     836             :         {
     837           0 :           rc = out_of_core ();
     838           0 :           goto leave;
     839             :         }
     840           0 :       *buf = '<';
     841           0 :       strcpy (buf+1, s);
     842           0 :       strcat (buf+1, ">");
     843           0 :       err = ksba_certreq_add_subject (cr, buf);
     844           0 :       xfree (buf);
     845           0 :       if (err)
     846             :         {
     847           0 :           log_error ("error setting the subject's alternate name: %s\n",
     848             :                      gpg_strerror (err));
     849           0 :           rc = err;
     850           0 :           goto leave;
     851             :         }
     852             :     }
     853             : 
     854           0 :   for (seq=0; (s = get_parameter_value (para, pNAMEDNS, seq)); seq++)
     855             :     {
     856           0 :       len = strlen (s);
     857           0 :       assert (len);
     858           0 :       snprintf (numbuf, DIM(numbuf), "%u:", (unsigned int)len);
     859           0 :       buf = p = xtrymalloc (11 + strlen (numbuf) + len + 3);
     860           0 :       if (!buf)
     861             :         {
     862           0 :           rc = out_of_core ();
     863           0 :           goto leave;
     864             :         }
     865           0 :       p = stpcpy (p, "(8:dns-name");
     866           0 :       p = stpcpy (p, numbuf);
     867           0 :       p = stpcpy (p, s);
     868           0 :       strcpy (p, ")");
     869             : 
     870           0 :       err = ksba_certreq_add_subject (cr, buf);
     871           0 :       xfree (buf);
     872           0 :       if (err)
     873             :         {
     874           0 :           log_error ("error setting the subject's alternate name: %s\n",
     875             :                      gpg_strerror (err));
     876           0 :           rc = err;
     877           0 :           goto leave;
     878             :         }
     879             :     }
     880             : 
     881           0 :   for (seq=0; (s = get_parameter_value (para, pNAMEURI, seq)); seq++)
     882             :     {
     883           0 :       len = strlen (s);
     884           0 :       assert (len);
     885           0 :       snprintf (numbuf, DIM(numbuf), "%u:", (unsigned int)len);
     886           0 :       buf = p = xtrymalloc (6 + strlen (numbuf) + len + 3);
     887           0 :       if (!buf)
     888             :         {
     889           0 :           rc = out_of_core ();
     890           0 :           goto leave;
     891             :         }
     892           0 :       p = stpcpy (p, "(3:uri");
     893           0 :       p = stpcpy (p, numbuf);
     894           0 :       p = stpcpy (p, s);
     895           0 :       strcpy (p, ")");
     896             : 
     897           0 :       err = ksba_certreq_add_subject (cr, buf);
     898           0 :       xfree (buf);
     899           0 :       if (err)
     900             :         {
     901           0 :           log_error ("error setting the subject's alternate name: %s\n",
     902             :                      gpg_strerror (err));
     903           0 :           rc = err;
     904           0 :           goto leave;
     905             :         }
     906             :     }
     907             : 
     908             : 
     909           0 :   err = ksba_certreq_set_public_key (cr, public);
     910           0 :   if (err)
     911             :     {
     912           0 :       log_error ("error setting the public key: %s\n",
     913             :                  gpg_strerror (err));
     914           0 :       rc = err;
     915           0 :       goto leave;
     916             :     }
     917             : 
     918             :   /* Set key usage flags.  */
     919           0 :   use = get_parameter_uint (para, pKEYUSAGE);
     920           0 :   if (use)
     921             :     {
     922             :       unsigned int mask, pos;
     923             :       unsigned char der[4];
     924             : 
     925           0 :       der[0] = 0x03;
     926           0 :       der[1] = 0x02;
     927           0 :       der[2] = 0;
     928           0 :       der[3] = 0;
     929           0 :       if ((use & GCRY_PK_USAGE_SIGN))
     930             :         {
     931             :           /* For signing only we encode the bits:
     932             :              KSBA_KEYUSAGE_DIGITAL_SIGNATURE
     933             :              KSBA_KEYUSAGE_NON_REPUDIATION  = 0b11 -> 0b11000000 */
     934           0 :           der[3] |= 0xc0;
     935             :         }
     936           0 :       if ((use & GCRY_PK_USAGE_ENCR))
     937             :         {
     938             :           /* For encrypt only we encode the bits:
     939             :              KSBA_KEYUSAGE_KEY_ENCIPHERMENT
     940             :              KSBA_KEYUSAGE_DATA_ENCIPHERMENT = 0b1100 -> 0b00110000 */
     941           0 :           der[3] |= 0x30;
     942             :         }
     943           0 :       if ((use & GCRY_PK_USAGE_CERT))
     944             :         {
     945             :           /* For certify only we encode the bits:
     946             :              KSBA_KEYUSAGE_KEY_CERT_SIGN
     947             :              KSBA_KEYUSAGE_CRL_SIGN      = 0b1100000 -> 0b00000110 */
     948           0 :           der[3] |= 0x06;
     949             :         }
     950             : 
     951             :       /* Count number of unused bits.  */
     952           0 :       for (mask=1, pos=0; pos < 8 * sizeof mask; pos++, mask <<= 1)
     953             :         {
     954           0 :           if ((der[3] & mask))
     955           0 :             break;
     956           0 :           der[2]++;
     957             :         }
     958             : 
     959           0 :       err = ksba_certreq_add_extension (cr, oidstr_keyUsage, 1, der, 4);
     960           0 :       if (err)
     961             :         {
     962           0 :           log_error ("error setting the key usage: %s\n",
     963             :                      gpg_strerror (err));
     964           0 :           rc = err;
     965           0 :           goto leave;
     966             :         }
     967             :     }
     968             : 
     969             : 
     970             :   /* See whether we want to create an X.509 certificate.  */
     971           0 :   string = get_parameter_value (para, pSERIAL, 0);
     972           0 :   if (string)
     973             :     {
     974           0 :       certmode = 1;
     975             : 
     976             :       /* Store the serial number.  */
     977           0 :       if (!strcmp (string, "random"))
     978             :         {
     979             :           char snbuf[3+8+1];
     980             : 
     981           0 :           memcpy (snbuf, "(8:", 3);
     982           0 :           gcry_create_nonce (snbuf+3, 8);
     983             :           /* Clear high bit to guarantee a positive integer.  */
     984           0 :           snbuf[3] &= 0x7f;
     985           0 :           snbuf[3+8] = ')';
     986           0 :           err = ksba_certreq_set_serial (cr, snbuf);
     987             :         }
     988             :       else
     989             :         {
     990             :           char *hexbuf;
     991             : 
     992             :           /* Allocate a buffer large enough to prefix the string with
     993             :              a '0' so to have an even number of digits.  Prepend two
     994             :              further '0' so that the binary result will have a leading
     995             :              0 byte and thus can't be the representation of a negative
     996             :              number.  Note that ksba_certreq_set_serial strips all
     997             :              unneeded leading 0 bytes.  */
     998           0 :           hexbuf = p = xtrymalloc (2 + 1 + strlen (string) + 1);
     999           0 :           if (!hexbuf)
    1000             :             {
    1001           0 :               err = gpg_error_from_syserror ();
    1002           0 :               goto leave;
    1003             :             }
    1004           0 :           if ((strlen (string) & 1))
    1005           0 :             *p++ = '0';
    1006           0 :           *p++ = '0';
    1007           0 :           *p++ = '0';
    1008           0 :           strcpy (p, string);
    1009           0 :           for (p=hexbuf, len=0; p[0] && p[1]; p += 2)
    1010           0 :             ((unsigned char*)hexbuf)[len++] = xtoi_2 (p);
    1011             :           /* Now build the S-expression.  */
    1012           0 :           snprintf (numbuf, DIM(numbuf), "%u:", (unsigned int)len);
    1013           0 :           buf = p = xtrymalloc (1 + strlen (numbuf) + len + 1 + 1);
    1014           0 :           if (!buf)
    1015             :             {
    1016           0 :               err = gpg_error_from_syserror ();
    1017           0 :               xfree (hexbuf);
    1018           0 :               goto leave;
    1019             :             }
    1020           0 :           p = stpcpy (stpcpy (buf, "("), numbuf);
    1021           0 :           memcpy (p, hexbuf, len);
    1022           0 :           p += len;
    1023           0 :           strcpy (p, ")");
    1024           0 :           xfree (hexbuf);
    1025           0 :           err = ksba_certreq_set_serial (cr, buf);
    1026           0 :           xfree (buf);
    1027             :         }
    1028           0 :       if (err)
    1029             :         {
    1030           0 :           log_error ("error setting the serial number: %s\n",
    1031             :                      gpg_strerror (err));
    1032           0 :           goto leave;
    1033             :         }
    1034             : 
    1035             : 
    1036             :       /* Store the issuer DN.  If no issuer DN is given and no signing
    1037             :          key has been set we add the standalone extension and the
    1038             :          basic constraints to mark it as a self-signed CA
    1039             :          certificate.  */
    1040           0 :       string = get_parameter_value (para, pISSUERDN, 0);
    1041           0 :       if (string)
    1042             :         {
    1043             :           /* Issuer DN given.  Note that this may be the same as the
    1044             :              subject DN and thus this could as well be a self-signed
    1045             :              certificate.  However the caller needs to explicitly
    1046             :              specify basicConstraints and so forth.  */
    1047           0 :           err = ksba_certreq_set_issuer (cr, string);
    1048           0 :           if (err)
    1049             :             {
    1050           0 :               log_error ("error setting the issuer DN: %s\n",
    1051             :                          gpg_strerror (err));
    1052           0 :               goto leave;
    1053             :             }
    1054             : 
    1055             :         }
    1056           0 :       else if (!string && !sigkey)
    1057             :         {
    1058             :           /* Self-signed certificate requested.  Add basicConstraints
    1059             :              and the custom GnuPG standalone extension.  */
    1060           0 :           err = ksba_certreq_add_extension (cr, oidstr_basicConstraints, 1,
    1061             :                                             "\x30\x03\x01\x01\xff", 5);
    1062           0 :           if (err)
    1063           0 :             goto leave;
    1064           0 :           err = ksba_certreq_add_extension (cr, oidstr_standaloneCertificate, 0,
    1065             :                                             "\x01\x01\xff", 3);
    1066           0 :           if (err)
    1067           0 :             goto leave;
    1068             :         }
    1069             : 
    1070             :       /* Store the creation date.  */
    1071           0 :       string = get_parameter_value (para, pNOTBEFORE, 0);
    1072           0 :       if (string)
    1073             :         {
    1074           0 :           if (!string2isotime (atime, string))
    1075           0 :             BUG (); /* We already checked the value.  */
    1076             :         }
    1077             :       else
    1078           0 :         gnupg_get_isotime (atime);
    1079           0 :       err = ksba_certreq_set_validity (cr, 0, atime);
    1080           0 :       if (err)
    1081             :         {
    1082           0 :           log_error ("error setting the creation date: %s\n",
    1083             :                      gpg_strerror (err));
    1084           0 :           goto leave;
    1085             :         }
    1086             : 
    1087             : 
    1088             :       /* Store the expire date.  If it is not given, libksba inserts a
    1089             :          default value.  */
    1090           0 :       string = get_parameter_value (para, pNOTAFTER, 0);
    1091           0 :       if (string)
    1092             :         {
    1093           0 :           if (!string2isotime (atime, string))
    1094           0 :             BUG (); /* We already checked the value.  */
    1095           0 :           err = ksba_certreq_set_validity (cr, 1, atime);
    1096           0 :           if (err)
    1097             :             {
    1098           0 :               log_error ("error setting the expire date: %s\n",
    1099             :                          gpg_strerror (err));
    1100           0 :               goto leave;
    1101             :             }
    1102             :         }
    1103             : 
    1104             : 
    1105             :       /* Figure out the signing algorithm.  If no sigkey has been
    1106             :          given we set it to the public key to create a self-signed
    1107             :          certificate. */
    1108           0 :       if (!sigkey)
    1109           0 :         sigkey = public;
    1110             : 
    1111             :       {
    1112             :         unsigned char *siginfo;
    1113             : 
    1114           0 :         err = transform_sigval (sigkey,
    1115             :                                 gcry_sexp_canon_len (sigkey, 0, NULL, NULL),
    1116             :                                 mdalgo, &siginfo, NULL);
    1117           0 :         if (!err)
    1118             :           {
    1119           0 :             err = ksba_certreq_set_siginfo (cr, siginfo);
    1120           0 :             xfree (siginfo);
    1121             :           }
    1122           0 :         if (err)
    1123             :           {
    1124           0 :             log_error ("error setting the siginfo: %s\n",
    1125             :                        gpg_strerror (err));
    1126           0 :             rc = err;
    1127           0 :             goto leave;
    1128             :           }
    1129             :       }
    1130             : 
    1131             :       /* Insert the AuthorityKeyId.  */
    1132           0 :       string = get_parameter_value (para, pAUTHKEYID, 0);
    1133           0 :       if (string)
    1134             :         {
    1135             :           char *hexbuf;
    1136             : 
    1137             :           /* Allocate a buffer for in-place conversion.  We also add 4
    1138             :              extra bytes space for the tags and lengths fields.  */
    1139           0 :           hexbuf = xtrymalloc (4 + strlen (string) + 1);
    1140           0 :           if (!hexbuf)
    1141             :             {
    1142           0 :               err = gpg_error_from_syserror ();
    1143           0 :               goto leave;
    1144             :             }
    1145           0 :           strcpy (hexbuf+4, string);
    1146           0 :           for (p=hexbuf+4, len=0; p[0] && p[1]; p += 2)
    1147           0 :             ((unsigned char*)hexbuf)[4+len++] = xtoi_2 (p);
    1148           0 :           if (len > 125)
    1149             :             {
    1150           0 :               err = gpg_error (GPG_ERR_TOO_LARGE);
    1151           0 :               xfree (hexbuf);
    1152           0 :               goto leave;
    1153             :             }
    1154           0 :           hexbuf[0] = 0x30;  /* Tag for a Sequence.  */
    1155           0 :           hexbuf[1] = len+2;
    1156           0 :           hexbuf[2] = 0x80;  /* Context tag for an implicit Octet string.  */
    1157           0 :           hexbuf[3] = len;
    1158           0 :           err = ksba_certreq_add_extension (cr, oidstr_authorityKeyIdentifier,
    1159             :                                             0,
    1160             :                                             hexbuf, 4+len);
    1161           0 :           xfree (hexbuf);
    1162           0 :           if (err)
    1163             :             {
    1164           0 :               log_error ("error setting the authority-key-id: %s\n",
    1165             :                          gpg_strerror (err));
    1166           0 :               goto leave;
    1167             :             }
    1168             :         }
    1169             : 
    1170             :       /* Insert the SubjectKeyId.  */
    1171           0 :       string = get_parameter_value (para, pSUBJKEYID, 0);
    1172           0 :       if (string)
    1173             :         {
    1174             :           char *hexbuf;
    1175             : 
    1176             :           /* Allocate a buffer for in-place conversion.  We also add 2
    1177             :              extra bytes space for the tag and length field.  */
    1178           0 :           hexbuf = xtrymalloc (2 + strlen (string) + 1);
    1179           0 :           if (!hexbuf)
    1180             :             {
    1181           0 :               err = gpg_error_from_syserror ();
    1182           0 :               goto leave;
    1183             :             }
    1184           0 :           strcpy (hexbuf+2, string);
    1185           0 :           for (p=hexbuf+2, len=0; p[0] && p[1]; p += 2)
    1186           0 :             ((unsigned char*)hexbuf)[2+len++] = xtoi_2 (p);
    1187           0 :           if (len > 127)
    1188             :             {
    1189           0 :               err = gpg_error (GPG_ERR_TOO_LARGE);
    1190           0 :               xfree (hexbuf);
    1191           0 :               goto leave;
    1192             :             }
    1193           0 :           hexbuf[0] = 0x04;  /* Tag for an Octet string.  */
    1194           0 :           hexbuf[1] = len;
    1195           0 :           err = ksba_certreq_add_extension (cr, oidstr_subjectKeyIdentifier, 0,
    1196             :                                             hexbuf, 2+len);
    1197           0 :           xfree (hexbuf);
    1198           0 :           if (err)
    1199             :             {
    1200           0 :               log_error ("error setting the subject-key-id: %s\n",
    1201             :                          gpg_strerror (err));
    1202           0 :               goto leave;
    1203             :             }
    1204             :         }
    1205             : 
    1206             :       /* Insert additional extensions.  */
    1207           0 :       for (seq=0; (string = get_parameter_value (para, pEXTENSION, seq)); seq++)
    1208             :         {
    1209             :           char *hexbuf;
    1210             :           char *oidstr;
    1211           0 :           int crit = 0;
    1212             : 
    1213           0 :           s = strpbrk (string, " \t:");
    1214           0 :           if (!s)
    1215             :             {
    1216           0 :               err = gpg_error (GPG_ERR_INTERNAL);
    1217           0 :               goto leave;
    1218             :             }
    1219             : 
    1220           0 :           oidstr = xtrymalloc (s - string + 1);
    1221           0 :           if (!oidstr)
    1222             :             {
    1223           0 :               err = gpg_error_from_syserror ();
    1224           0 :               goto leave;
    1225             :             }
    1226           0 :           memcpy (oidstr, string, (s-string));
    1227           0 :           oidstr[(s-string)] = 0;
    1228             : 
    1229           0 :           s++;
    1230           0 :           while (spacep (s))
    1231           0 :             s++;
    1232           0 :           if (!*s)
    1233             :             {
    1234           0 :               err = gpg_error (GPG_ERR_INTERNAL);
    1235           0 :               xfree (oidstr);
    1236           0 :               goto leave;
    1237             :             }
    1238             : 
    1239           0 :           if (strchr ("cC", *s))
    1240           0 :             crit = 1;
    1241           0 :           s++;
    1242           0 :           while (spacep (s))
    1243           0 :             s++;
    1244           0 :           if (*s == ':')
    1245           0 :             s++;
    1246           0 :           while (spacep (s))
    1247           0 :             s++;
    1248             : 
    1249           0 :           hexbuf = xtrystrdup (s);
    1250           0 :           if (!hexbuf)
    1251             :             {
    1252           0 :               err = gpg_error_from_syserror ();
    1253           0 :               xfree (oidstr);
    1254           0 :               goto leave;
    1255             :             }
    1256           0 :           for (p=hexbuf, len=0; p[0] && p[1]; p += 2)
    1257           0 :             ((unsigned char*)hexbuf)[len++] = xtoi_2 (p);
    1258           0 :           err = ksba_certreq_add_extension (cr, oidstr, crit,
    1259             :                                             hexbuf, len);
    1260           0 :           xfree (oidstr);
    1261           0 :           xfree (hexbuf);
    1262             :         }
    1263             :     }
    1264             :   else
    1265           0 :     sigkey = public;
    1266             : 
    1267             :   do
    1268             :     {
    1269           0 :       err = ksba_certreq_build (cr, &stopreason);
    1270           0 :       if (err)
    1271             :         {
    1272           0 :           log_error ("ksba_certreq_build failed: %s\n", gpg_strerror (err));
    1273           0 :           rc = err;
    1274           0 :           goto leave;
    1275             :         }
    1276           0 :       if (stopreason == KSBA_SR_NEED_SIG)
    1277             :         {
    1278             :           gcry_sexp_t s_pkey;
    1279             :           size_t n;
    1280             :           unsigned char grip[20];
    1281             :           char hexgrip[41];
    1282             :           unsigned char *sigval, *newsigval;
    1283             :           size_t siglen;
    1284             : 
    1285           0 :           n = gcry_sexp_canon_len (sigkey, 0, NULL, NULL);
    1286           0 :           if (!n)
    1287             :             {
    1288           0 :               log_error ("libksba did not return a proper S-Exp\n");
    1289           0 :               rc = gpg_error (GPG_ERR_BUG);
    1290           0 :               goto leave;
    1291             :             }
    1292           0 :           rc = gcry_sexp_sscan (&s_pkey, NULL, (const char*)sigkey, n);
    1293           0 :           if (rc)
    1294             :             {
    1295           0 :               log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
    1296           0 :               goto leave;
    1297             :             }
    1298           0 :           if ( !gcry_pk_get_keygrip (s_pkey, grip) )
    1299             :             {
    1300           0 :               rc = gpg_error (GPG_ERR_GENERAL);
    1301           0 :               log_error ("can't figure out the keygrip\n");
    1302           0 :               gcry_sexp_release (s_pkey);
    1303           0 :               goto leave;
    1304             :             }
    1305           0 :           gcry_sexp_release (s_pkey);
    1306           0 :           bin2hex (grip, 20, hexgrip);
    1307             : 
    1308           0 :           log_info ("about to sign the %s for key: &%s\n",
    1309             :                     certmode? "certificate":"CSR", hexgrip);
    1310             : 
    1311           0 :           if (carddirect)
    1312           0 :             rc = gpgsm_scd_pksign (ctrl, carddirect, NULL,
    1313             :                                    gcry_md_read (md, mdalgo),
    1314           0 :                                    gcry_md_get_algo_dlen (mdalgo),
    1315             :                                    mdalgo,
    1316             :                                    &sigval, &siglen);
    1317             :           else
    1318             :             {
    1319             :               char *orig_codeset;
    1320             :               char *desc;
    1321             : 
    1322           0 :               orig_codeset = i18n_switchto_utf8 ();
    1323           0 :               desc = percent_plus_escape
    1324           0 :                 (_("To complete this certificate request please enter"
    1325             :                    " the passphrase for the key you just created once"
    1326             :                    " more.\n"));
    1327           0 :               i18n_switchback (orig_codeset);
    1328           0 :               rc = gpgsm_agent_pksign (ctrl, hexgrip, desc,
    1329             :                                        gcry_md_read(md, mdalgo),
    1330           0 :                                        gcry_md_get_algo_dlen (mdalgo),
    1331             :                                        mdalgo,
    1332             :                                        &sigval, &siglen);
    1333           0 :               xfree (desc);
    1334             :             }
    1335           0 :           if (rc)
    1336             :             {
    1337           0 :               log_error ("signing failed: %s\n", gpg_strerror (rc));
    1338           0 :               goto leave;
    1339             :             }
    1340             : 
    1341           0 :           err = transform_sigval (sigval, siglen, mdalgo,
    1342             :                                   &newsigval, NULL);
    1343           0 :           xfree (sigval);
    1344           0 :           if (!err)
    1345             :             {
    1346           0 :               err = ksba_certreq_set_sig_val (cr, newsigval);
    1347           0 :               xfree (newsigval);
    1348             :             }
    1349           0 :           if (err)
    1350             :             {
    1351           0 :               log_error ("failed to store the sig_val: %s\n",
    1352             :                          gpg_strerror (err));
    1353           0 :               rc = err;
    1354           0 :               goto leave;
    1355             :             }
    1356             :         }
    1357             :     }
    1358           0 :   while (stopreason != KSBA_SR_READY);
    1359             : 
    1360             : 
    1361             :  leave:
    1362           0 :   gcry_md_close (md);
    1363           0 :   ksba_certreq_release (cr);
    1364           0 :   return rc;
    1365             : }
    1366             : 
    1367             : 
    1368             : 
    1369             : /* Create a new key by reading the parameters from IN_FP.  Multiple
    1370             :    keys may be created */
    1371             : int
    1372           0 : gpgsm_genkey (ctrl_t ctrl, estream_t in_stream, estream_t out_stream)
    1373             : {
    1374             :   int rc;
    1375             : 
    1376           0 :   rc = read_parameters (ctrl, in_stream, out_stream);
    1377           0 :   if (rc)
    1378             :     {
    1379           0 :       log_error ("error creating certificate request: %s <%s>\n",
    1380             :                  gpg_strerror (rc), gpg_strsource (rc));
    1381           0 :       goto leave;
    1382             :     }
    1383             : 
    1384             :  leave:
    1385           0 :   return rc;
    1386             : }

Generated by: LCOV version 1.11