LCOV - code coverage report
Current view: top level - agent - divert-scd.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 218 0.0 %
Date: 2016-11-29 15:00:56 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /* divert-scd.c - divert operations to the scdaemon
       2             :  *      Copyright (C) 2002, 2003, 2009 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 3 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, see <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <errno.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <ctype.h>
      26             : #include <assert.h>
      27             : #include <unistd.h>
      28             : #include <sys/stat.h>
      29             : 
      30             : #include "agent.h"
      31             : #include "i18n.h"
      32             : #include "sexp-parse.h"
      33             : 
      34             : 
      35             : static int
      36           0 : ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
      37             : {
      38             :   int rc, i;
      39             :   char *serialno;
      40           0 :   int no_card = 0;
      41             :   char *desc;
      42             :   char *want_sn, *want_kid;
      43             :   int want_sn_displen;
      44             : 
      45           0 :   *r_kid = NULL;
      46             : 
      47           0 :   rc = parse_shadow_info (shadow_info, &want_sn, &want_kid, NULL);
      48           0 :   if (rc)
      49           0 :     return rc;
      50             : 
      51             :   /* We assume that a 20 byte serial number is a standard one which
      52             :      has the property to have a zero in the last nibble (Due to BCD
      53             :      representation).  We don't display this '0' because it may
      54             :      confuse the user.  */
      55           0 :   want_sn_displen = strlen (want_sn);
      56           0 :   if (want_sn_displen == 20 && want_sn[19] == '0')
      57           0 :     want_sn_displen--;
      58             : 
      59             :   for (;;)
      60             :     {
      61           0 :       rc = agent_card_serialno (ctrl, &serialno);
      62           0 :       if (!rc)
      63             :         {
      64           0 :           log_debug ("detected card with S/N %s\n", serialno);
      65           0 :           i = strcmp (serialno, want_sn);
      66           0 :           xfree (serialno);
      67           0 :           serialno = NULL;
      68           0 :           if (!i)
      69             :             {
      70           0 :               xfree (want_sn);
      71           0 :               *r_kid = want_kid;
      72           0 :               return 0; /* yes, we have the correct card */
      73             :             }
      74             :         }
      75           0 :       else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
      76             :         {
      77           0 :           log_debug ("no card present\n");
      78           0 :           rc = 0;
      79           0 :           no_card = 1;
      80             :         }
      81             :       else
      82             :         {
      83           0 :           log_error ("error accessing card: %s\n", gpg_strerror (rc));
      84             :         }
      85             : 
      86           0 :       if (!rc)
      87             :         {
      88           0 :           if (asprintf (&desc,
      89             :                     "%s:%%0A%%0A"
      90             :                     "  \"%.*s\"",
      91             :                         no_card
      92             :                         ? L_("Please insert the card with serial number")
      93             :                         : L_("Please remove the current card and "
      94             :                              "insert the one with serial number"),
      95             :                     want_sn_displen, want_sn) < 0)
      96             :             {
      97           0 :               rc = out_of_core ();
      98             :             }
      99             :           else
     100             :             {
     101           0 :               rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
     102           0 :               if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK &&
     103           0 :                   gpg_err_code (rc) == GPG_ERR_NO_PIN_ENTRY)
     104           0 :                 rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
     105             : 
     106           0 :               xfree (desc);
     107             :             }
     108             :         }
     109           0 :       if (rc)
     110             :         {
     111           0 :           xfree (want_sn);
     112           0 :           xfree (want_kid);
     113           0 :           return rc;
     114             :         }
     115           0 :     }
     116             : }
     117             : 
     118             : 
     119             : /* Put the DIGEST into an DER encoded container and return it in R_VAL. */
     120             : static int
     121           0 : encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
     122             :                     unsigned char **r_val, size_t *r_len)
     123             : {
     124             :   unsigned char *frame;
     125             :   unsigned char asn[100];
     126             :   size_t asnlen;
     127             : 
     128           0 :   *r_val = NULL;
     129           0 :   *r_len = 0;
     130             : 
     131           0 :   asnlen = DIM(asn);
     132           0 :   if (!algo || gcry_md_test_algo (algo))
     133           0 :     return gpg_error (GPG_ERR_DIGEST_ALGO);
     134           0 :   if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
     135             :     {
     136           0 :       log_error ("no object identifier for algo %d\n", algo);
     137           0 :       return gpg_error (GPG_ERR_INTERNAL);
     138             :     }
     139             : 
     140           0 :   frame = xtrymalloc (asnlen + digestlen);
     141           0 :   if (!frame)
     142           0 :     return out_of_core ();
     143           0 :   memcpy (frame, asn, asnlen);
     144           0 :   memcpy (frame+asnlen, digest, digestlen);
     145           0 :   if (DBG_CRYPTO)
     146           0 :     log_printhex ("encoded hash:", frame, asnlen+digestlen);
     147             : 
     148           0 :   *r_val = frame;
     149           0 :   *r_len = asnlen+digestlen;
     150           0 :   return 0;
     151             : }
     152             : 
     153             : 
     154             : /* Callback used to ask for the PIN which should be set into BUF.  The
     155             :    buf has been allocated by the caller and is of size MAXBUF which
     156             :    includes the terminating null.  The function should return an UTF-8
     157             :    string with the passphrase, the buffer may optionally be padded
     158             :    with arbitrary characters.
     159             : 
     160             :    INFO gets displayed as part of a generic string.  However if the
     161             :    first character of INFO is a vertical bar all up to the next
     162             :    verical bar are considered flags and only everything after the
     163             :    second vertical bar gets displayed as the full prompt.
     164             : 
     165             :    Flags:
     166             : 
     167             :       'N' = New PIN, this requests a second prompt to repeat the
     168             :             PIN.  If the PIN is not correctly repeated it starts from
     169             :             all over.
     170             :       'A' = The PIN is an Admin PIN, SO-PIN or alike.
     171             :       'P' = The PIN is a PUK (Personal Unblocking Key).
     172             :       'R' = The PIN is a Reset Code.
     173             : 
     174             :    Example:
     175             : 
     176             :      "|AN|Please enter the new security officer's PIN"
     177             : 
     178             :    The text "Please ..." will get displayed and the flags 'A' and 'N'
     179             :    are considered.
     180             :  */
     181             : static int
     182           0 : getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
     183             : {
     184             :   struct pin_entry_info_s *pi;
     185             :   int rc;
     186           0 :   ctrl_t ctrl = opaque;
     187             :   const char *ends, *s;
     188           0 :   int any_flags = 0;
     189           0 :   int newpin = 0;
     190           0 :   int resetcode = 0;
     191           0 :   int is_puk = 0;
     192           0 :   const char *again_text = NULL;
     193           0 :   const char *prompt = "PIN";
     194             : 
     195           0 :   if (buf && maxbuf < 2)
     196           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     197             : 
     198             :   /* Parse the flags. */
     199           0 :   if (info && *info =='|' && (ends=strchr (info+1, '|')))
     200             :     {
     201           0 :       for (s=info+1; s < ends; s++)
     202             :         {
     203           0 :           if (*s == 'A')
     204           0 :             prompt = L_("Admin PIN");
     205           0 :           else if (*s == 'P')
     206             :             {
     207             :               /* TRANSLATORS: A PUK is the Personal Unblocking Code
     208             :                  used to unblock a PIN. */
     209           0 :               prompt = L_("PUK");
     210           0 :               is_puk = 1;
     211             :             }
     212           0 :           else if (*s == 'N')
     213           0 :             newpin = 1;
     214           0 :           else if (*s == 'R')
     215             :             {
     216           0 :               prompt = L_("Reset Code");
     217           0 :               resetcode = 1;
     218             :             }
     219             :         }
     220           0 :       info = ends+1;
     221           0 :       any_flags = 1;
     222             :     }
     223           0 :   else if (info && *info == '|')
     224           0 :     log_debug ("pin_cb called without proper PIN info hack\n");
     225             : 
     226             :   /* If BUF has been passed as NULL, we are in pinpad mode: The
     227             :      callback opens the popup and immediately returns. */
     228           0 :   if (!buf)
     229             :     {
     230           0 :       if (maxbuf == 0) /* Close the pinentry. */
     231             :         {
     232           0 :           agent_popup_message_stop (ctrl);
     233           0 :           rc = 0;
     234             :         }
     235           0 :       else if (maxbuf == 1)  /* Open the pinentry. */
     236             :         {
     237           0 :           if (info)
     238             :             {
     239             :               char *desc;
     240             : 
     241           0 :               if ( asprintf (&desc,
     242             :                              L_("%s%%0A%%0AUse the reader's pinpad for input."),
     243             :                              info) < 0 )
     244           0 :                 rc = gpg_error_from_syserror ();
     245             :               else
     246             :                 {
     247           0 :                   rc = agent_popup_message_start (ctrl, desc, NULL);
     248           0 :                   xfree (desc);
     249             :                 }
     250             :             }
     251             :           else
     252           0 :             rc = agent_popup_message_start (ctrl, NULL, NULL);
     253             :         }
     254             :       else
     255           0 :         rc = gpg_error (GPG_ERR_INV_VALUE);
     256           0 :       return rc;
     257             :     }
     258             : 
     259             :   /* FIXME: keep PI and TRIES in OPAQUE.  Frankly this is a whole
     260             :      mess because we should call the card's verify function from the
     261             :      pinentry check pin CB. */
     262             :  again:
     263           0 :   pi = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
     264           0 :   if (!pi)
     265           0 :     return gpg_error_from_syserror ();
     266           0 :   pi->max_length = maxbuf-1;
     267           0 :   pi->min_digits = 0;  /* we want a real passphrase */
     268           0 :   pi->max_digits = 16;
     269           0 :   pi->max_tries = 3;
     270             : 
     271           0 :   if (any_flags)
     272             :     {
     273           0 :       rc = agent_askpin (ctrl, info, prompt, again_text, pi, NULL, 0);
     274           0 :       again_text = NULL;
     275           0 :       if (!rc && newpin)
     276             :         {
     277             :           struct pin_entry_info_s *pi2;
     278           0 :           pi2 = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
     279           0 :           if (!pi2)
     280             :             {
     281           0 :               rc = gpg_error_from_syserror ();
     282           0 :               xfree (pi);
     283           0 :               return rc;
     284             :             }
     285           0 :           pi2->max_length = maxbuf-1;
     286           0 :           pi2->min_digits = 0;
     287           0 :           pi2->max_digits = 16;
     288           0 :           pi2->max_tries = 1;
     289           0 :           rc = agent_askpin (ctrl,
     290             :                              (resetcode?
     291             :                               L_("Repeat this Reset Code"):
     292             :                               is_puk?
     293           0 :                               L_("Repeat this PUK"):
     294             :                               L_("Repeat this PIN")),
     295             :                              prompt, NULL, pi2, NULL, 0);
     296           0 :           if (!rc && strcmp (pi->pin, pi2->pin))
     297             :             {
     298           0 :               again_text = (resetcode?
     299           0 :                             L_("Reset Code not correctly repeated; try again"):
     300             :                             is_puk?
     301           0 :                             L_("PUK not correctly repeated; try again"):
     302             :                             L_("PIN not correctly repeated; try again"));
     303           0 :               xfree (pi2);
     304           0 :               xfree (pi);
     305           0 :               goto again;
     306             :             }
     307           0 :           xfree (pi2);
     308             :         }
     309             :     }
     310             :   else
     311             :     {
     312             :       char *desc;
     313           0 :       if ( asprintf (&desc,
     314             :                      L_("Please enter the PIN%s%s%s to unlock the card"),
     315             :                      info? " (":"",
     316             :                      info? info:"",
     317             :                      info? ")":"") < 0)
     318           0 :         desc = NULL;
     319           0 :       rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi, NULL, 0);
     320           0 :       xfree (desc);
     321             :     }
     322             : 
     323           0 :   if (!rc)
     324             :     {
     325           0 :       strncpy (buf, pi->pin, maxbuf-1);
     326           0 :       buf[maxbuf-1] = 0;
     327             :     }
     328           0 :   xfree (pi);
     329           0 :   return rc;
     330             : }
     331             : 
     332             : 
     333             : 
     334             : 
     335             : int
     336           0 : divert_pksign (ctrl_t ctrl,
     337             :                const unsigned char *digest, size_t digestlen, int algo,
     338             :                const unsigned char *shadow_info, unsigned char **r_sig,
     339             :                size_t *r_siglen)
     340             : {
     341             :   int rc;
     342             :   char *kid;
     343             :   size_t siglen;
     344           0 :   unsigned char *sigval = NULL;
     345             : 
     346           0 :   rc = ask_for_card (ctrl, shadow_info, &kid);
     347           0 :   if (rc)
     348           0 :     return rc;
     349             : 
     350           0 :   if (algo == MD_USER_TLS_MD5SHA1)
     351             :     {
     352           0 :       int save = ctrl->use_auth_call;
     353           0 :       ctrl->use_auth_call = 1;
     354           0 :       rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
     355             :                               algo, digest, digestlen, &sigval, &siglen);
     356           0 :       ctrl->use_auth_call = save;
     357             :     }
     358             :   else
     359             :     {
     360             :       unsigned char *data;
     361             :       size_t ndata;
     362             : 
     363           0 :       rc = encode_md_for_card (digest, digestlen, algo, &data, &ndata);
     364           0 :       if (!rc)
     365             :         {
     366           0 :           rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
     367             :                                   algo, data, ndata, &sigval, &siglen);
     368           0 :           xfree (data);
     369             :         }
     370             :     }
     371             : 
     372           0 :   if (!rc)
     373             :     {
     374           0 :       *r_sig = sigval;
     375           0 :       *r_siglen = siglen;
     376             :     }
     377             : 
     378           0 :   xfree (kid);
     379             : 
     380           0 :   return rc;
     381             : }
     382             : 
     383             : 
     384             : /* Decrypt the the value given asn an S-expression in CIPHER using the
     385             :    key identified by SHADOW_INFO and return the plaintext in an
     386             :    allocated buffer in R_BUF.  The padding information is stored at
     387             :    R_PADDING with -1 for not known.  */
     388             : int
     389           0 : divert_pkdecrypt (ctrl_t ctrl,
     390             :                   const unsigned char *cipher,
     391             :                   const unsigned char *shadow_info,
     392             :                   char **r_buf, size_t *r_len, int *r_padding)
     393             : {
     394             :   int rc;
     395             :   char *kid;
     396             :   const unsigned char *s;
     397             :   size_t n;
     398             :   const unsigned char *ciphertext;
     399             :   size_t ciphertextlen;
     400             :   char *plaintext;
     401             :   size_t plaintextlen;
     402             : 
     403           0 :   *r_padding = -1;
     404             : 
     405           0 :   s = cipher;
     406           0 :   if (*s != '(')
     407           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     408           0 :   s++;
     409           0 :   n = snext (&s);
     410           0 :   if (!n)
     411           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     412           0 :   if (!smatch (&s, n, "enc-val"))
     413           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     414           0 :   if (*s != '(')
     415           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     416           0 :   s++;
     417           0 :   n = snext (&s);
     418           0 :   if (!n)
     419           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     420           0 :   if (smatch (&s, n, "rsa"))
     421             :     {
     422           0 :       if (*s != '(')
     423           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     424           0 :       s++;
     425           0 :       n = snext (&s);
     426           0 :       if (!n)
     427           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     428           0 :       if (!smatch (&s, n, "a"))
     429           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     430           0 :       n = snext (&s);
     431             :     }
     432           0 :   else if (smatch (&s, n, "ecdh"))
     433             :     {
     434           0 :       if (*s != '(')
     435           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     436           0 :       s++;
     437           0 :       n = snext (&s);
     438           0 :       if (!n)
     439           0 :         return gpg_error (GPG_ERR_INV_SEXP);
     440           0 :       if (smatch (&s, n, "s"))
     441             :         {
     442           0 :           n = snext (&s);
     443           0 :           s += n;
     444           0 :           if (*s++ != ')')
     445           0 :             return gpg_error (GPG_ERR_INV_SEXP);
     446           0 :           if (*s++ != '(')
     447           0 :             return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     448           0 :           n = snext (&s);
     449           0 :           if (!n)
     450           0 :             return gpg_error (GPG_ERR_INV_SEXP);
     451             :         }
     452           0 :       if (!smatch (&s, n, "e"))
     453           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     454           0 :       n = snext (&s);
     455             :     }
     456             :   else
     457           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     458             : 
     459           0 :   if (!n)
     460           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     461           0 :   ciphertext = s;
     462           0 :   ciphertextlen = n;
     463             : 
     464           0 :   rc = ask_for_card (ctrl, shadow_info, &kid);
     465           0 :   if (rc)
     466           0 :     return rc;
     467             : 
     468           0 :   rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl,
     469             :                              ciphertext, ciphertextlen,
     470             :                              &plaintext, &plaintextlen, r_padding);
     471           0 :   if (!rc)
     472             :     {
     473           0 :       *r_buf = plaintext;
     474           0 :       *r_len = plaintextlen;
     475             :     }
     476           0 :   xfree (kid);
     477           0 :   return rc;
     478             : }
     479             : 
     480             : int
     481           0 : divert_writekey (ctrl_t ctrl, int force, const char *serialno,
     482             :                  const char *id, const char *keydata, size_t keydatalen)
     483             : {
     484           0 :   return agent_card_writekey (ctrl, force, serialno, id, keydata, keydatalen,
     485             :                               getpin_cb, ctrl);
     486             : }
     487             : 
     488             : int
     489           0 : divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context)
     490             : {
     491           0 :   return agent_card_scd (ctrl, cmdline, getpin_cb, ctrl, assuan_context);
     492             : }

Generated by: LCOV version 1.11