gpg: Also detect a plaintext packet before an encrypted packet.
[gnupg.git] / scd / iso7816.c
index 8d0f105..29208c2 100644 (file)
@@ -14,7 +14,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -32,8 +32,8 @@
 #include "options.h"
 #include "errors.h"
 #include "memory.h"
-#include "util.h"
-#include "i18n.h"
+#include "../common/util.h"
+#include "../common/i18n.h"
 #else /* GNUPG_MAJOR_VERSION != 1 */
 #include "scdaemon.h"
 #endif /* GNUPG_MAJOR_VERSION != 1 */
@@ -64,7 +64,7 @@ map_sw (int sw)
   switch (sw)
     {
     case SW_EEPROM_FAILURE: ec = GPG_ERR_HARDWARE; break;
-    case SW_TERM_STATE:     ec = GPG_ERR_CARD; break;
+    case SW_TERM_STATE:     ec = GPG_ERR_OBJ_TERM_STATE; break;
     case SW_WRONG_LENGTH:   ec = GPG_ERR_INV_VALUE; break;
     case SW_SM_NOT_SUP:     ec = GPG_ERR_NOT_SUPPORTED; break;
     case SW_CC_NOT_SUP:     ec = GPG_ERR_NOT_SUPPORTED; break;
@@ -93,8 +93,9 @@ map_sw (int sw)
     case SW_HOST_CARD_IO_ERROR:  ec = GPG_ERR_EIO; break;
     case SW_HOST_GENERAL_ERROR:  ec = GPG_ERR_GENERAL; break;
     case SW_HOST_NO_READER:      ec = GPG_ERR_ENODEV; break;
-    case SW_HOST_ABORTED:        ec = GPG_ERR_CANCELED; break;
-    case SW_HOST_NO_KEYPAD:      ec = GPG_ERR_NOT_SUPPORTED; break;
+    case SW_HOST_ABORTED:        ec = GPG_ERR_INV_RESPONSE; break;
+    case SW_HOST_NO_PINPAD:      ec = GPG_ERR_NOT_SUPPORTED; break;
+    case SW_HOST_CANCELLED:      ec = GPG_ERR_CANCELED; break;
 
     default:
       if ((sw & 0x010000))
@@ -138,8 +139,7 @@ iso7816_select_application (int slot, const char *aid, size_t aidlen,
 
 
 gpg_error_t
-iso7816_select_file (int slot, int tag, int is_dir,
-                     unsigned char **result, size_t *resultlen)
+iso7816_select_file (int slot, int tag, int is_dir)
 {
   int sw, p0, p1;
   unsigned char tagbuf[2];
@@ -147,41 +147,22 @@ iso7816_select_file (int slot, int tag, int is_dir,
   tagbuf[0] = (tag >> 8) & 0xff;
   tagbuf[1] = tag & 0xff;
 
-  if (result || resultlen)
-    {
-      *result = NULL;
-      *resultlen = 0;
-      return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
-    }
-  else
-    {
-      p0 = (tag == 0x3F00)? 0: is_dir? 1:2;
-      p1 = 0x0c; /* No FC return. */
-      sw = apdu_send_simple (slot, 0, 0x00, CMD_SELECT_FILE,
-                             p0, p1, 2, (char*)tagbuf );
-      return map_sw (sw);
-    }
-
-  return 0;
+  p0 = (tag == 0x3F00)? 0: is_dir? 1:2;
+  p1 = 0x0c; /* No FC return. */
+  sw = apdu_send_simple (slot, 0, 0x00, CMD_SELECT_FILE,
+                         p0, p1, 2, (char*)tagbuf );
+  return map_sw (sw);
 }
 
 
 /* Do a select file command with a direct path. */
 gpg_error_t
-iso7816_select_path (int slot, const unsigned short *path, size_t pathlen,
-                     unsigned char **result, size_t *resultlen)
+iso7816_select_path (int slot, const unsigned short *path, size_t pathlen)
 {
   int sw, p0, p1;
   unsigned char buffer[100];
   int buflen;
 
-  if (result || resultlen)
-    {
-      *result = NULL;
-      *resultlen = 0;
-      return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
-    }
-
   if (pathlen/2 >= sizeof buffer)
     return gpg_error (GPG_ERR_TOO_LARGE);
 
@@ -224,7 +205,7 @@ iso7816_list_directory (int slot, int list_dirs,
 }
 
 
-/* This funcion sends an already formatted APDU to the card.  With
+/* This function sends an already formatted APDU to the card.  With
    HANDLE_MORE set to true a MORE DATA status will be handled
    internally.  The return value is a gpg error code (i.e. a mapped
    status word).  This is basically the same as apdu_send_direct but
@@ -267,35 +248,31 @@ iso7816_apdu_direct (int slot, const void *apdudata, size_t apdudatalen,
 
 
 /* Check whether the reader supports the ISO command code COMMAND on
-   the keypad.  Returns 0 on success.  */
+   the pinpad.  Returns 0 on success.  */
 gpg_error_t
-iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
+iso7816_check_pinpad (int slot, int command, pininfo_t *pininfo)
 {
   int sw;
 
-  sw = apdu_check_keypad (slot, command,
-                          pininfo->mode, pininfo->minlen, pininfo->maxlen,
-                          pininfo->padlen);
+  sw = apdu_check_pinpad (slot, command, pininfo);
   return iso7816_map_sw (sw);
 }
 
 
 /* Perform a VERIFY command on SLOT using the card holder verification
-   vector CHVNO.  With PININFO non-NULL the keypad of the reader will
+   vector CHVNO.  With PININFO non-NULL the pinpad of the reader will
    be used.  Returns 0 on success. */
 gpg_error_t
-iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo)
+iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo)
 {
   int sw;
 
-  sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno,
-                           pininfo->mode, pininfo->minlen, pininfo->maxlen,
-                           pininfo->padlen);
+  sw = apdu_pinpad_verify (slot, 0x00, CMD_VERIFY, 0, chvno, pininfo);
   return map_sw (sw);
 }
 
 /* Perform a VERIFY command on SLOT using the card holder verification
-   vector CHVNO with a CHV of lenght CHVLEN.  Returns 0 on success. */
+   vector CHVNO with a CHV of length CHVLEN.  Returns 0 on success. */
 gpg_error_t
 iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
 {
@@ -306,17 +283,17 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
 }
 
 /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
-   verification vector CHVNO.  With PININFO non-NULL the keypad of the
-   reader will be used.  */
+   verification vector CHVNO.  With PININFO non-NULL the pinpad of the
+   reader will be used.  If IS_EXCHANGE is 0, a "change reference
+   data" is done, otherwise an "exchange reference data".  */
 gpg_error_t
-iso7816_change_reference_data_kp (int slot, int chvno,
-                                  iso7816_pininfo_t *pininfo)
+iso7816_change_reference_data_kp (int slot, int chvno, int is_exchange,
+                                  pininfo_t *pininfo)
 {
   int sw;
 
-  sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, 0, chvno,
-                           pininfo->mode, pininfo->minlen, pininfo->maxlen,
-                           pininfo->padlen);
+  sw = apdu_pinpad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
+                          is_exchange ? 1 : 0, chvno, pininfo);
   return map_sw (sw);
 }
 
@@ -354,31 +331,6 @@ iso7816_change_reference_data (int slot, int chvno,
 
 
 gpg_error_t
-iso7816_reset_retry_counter_kp (int slot, int chvno,
-                                const char *newchv, size_t newchvlen,
-                                iso7816_pininfo_t *pininfo)
-{
-  int sw;
-
-  if (!newchv || !newchvlen )
-    return gpg_error (GPG_ERR_INV_VALUE);
-
-  /* FIXME:  The keypad mode has not yet been tested.  */
-  if (pininfo && pininfo->mode)
-    sw = apdu_send_simple_kp (slot, 0x00, CMD_RESET_RETRY_COUNTER,
-                           2, chvno, newchvlen, newchv,
-                           pininfo->mode,
-                           pininfo->minlen,
-                           pininfo->maxlen,
-                           pininfo->padlen);
-  else
-    sw = apdu_send_simple (slot, 0, 0x00, CMD_RESET_RETRY_COUNTER,
-                           2, chvno, newchvlen, newchv);
-  return map_sw (sw);
-}
-
-
-gpg_error_t
 iso7816_reset_retry_counter_with_rc (int slot, int chvno,
                                      const char *data, size_t datalen)
 {
@@ -397,7 +349,11 @@ gpg_error_t
 iso7816_reset_retry_counter (int slot, int chvno,
                              const char *newchv, size_t newchvlen)
 {
-  return iso7816_reset_retry_counter_kp (slot, chvno, newchv, newchvlen, NULL);
+  int sw;
+
+  sw = apdu_send_simple (slot, 0, 0x00, CMD_RESET_RETRY_COUNTER,
+                         2, chvno, newchvlen, newchv);
+  return map_sw (sw);
 }
 
 
@@ -629,8 +585,7 @@ iso7816_internal_authenticate (int slot, int extended_mode,
    (e.g. 4096 bytes), a value larger 256 used that value.  */
 static gpg_error_t
 do_generate_keypair (int slot, int extended_mode, int read_only,
-                     const unsigned char *data, size_t datalen,
-                     int le,
+                     const char *data, size_t datalen, int le,
                      unsigned char **result, size_t *resultlen)
 {
   int sw;
@@ -642,7 +597,7 @@ do_generate_keypair (int slot, int extended_mode, int read_only,
 
   sw = apdu_send_le (slot, extended_mode,
                      0x00, CMD_GENERATE_KEYPAIR, read_only? 0x81:0x80, 0,
-                     datalen, (const char*)data,
+                     datalen, data,
                      le >= 0 && le < 256? 256:le,
                      result, resultlen);
   if (sw != SW_SUCCESS)
@@ -660,7 +615,7 @@ do_generate_keypair (int slot, int extended_mode, int read_only,
 
 gpg_error_t
 iso7816_generate_keypair (int slot, int extended_mode,
-                          const unsigned char *data, size_t datalen,
+                          const char *data, size_t datalen,
                           int le,
                           unsigned char **result, size_t *resultlen)
 {
@@ -671,7 +626,7 @@ iso7816_generate_keypair (int slot, int extended_mode,
 
 gpg_error_t
 iso7816_read_public_key (int slot, int extended_mode,
-                         const unsigned char *data, size_t datalen,
+                         const char *data, size_t datalen,
                          int le,
                          unsigned char **result, size_t *resultlen)
 {