Skip to content

Commit

Permalink
Dell reader cannot handle PIN without padding
Browse files Browse the repository at this point in the history
  • Loading branch information
Javier Serrano Polo committed Jan 18, 2014
1 parent 9f90cfa commit 83142d4
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 14 deletions.
2 changes: 2 additions & 0 deletions src/libopensc/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ libopensc_la_SOURCES = \
pkcs15-prkey.c pkcs15-pubkey.c pkcs15-skey.c \
pkcs15-sec.c pkcs15-algo.c pkcs15-cache.c pkcs15-syn.c \
\
quirks-reader.c \
\
muscle.c muscle-filesystem.c \
\
ctbcs.c reader-ctapi.c reader-pcsc.c reader-openct.c \
Expand Down
3 changes: 3 additions & 0 deletions src/libopensc/internal-winscard.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ typedef LONG (PCSC_API *SCardGetAttrib_t)(SCARDHANDLE hCard, DWORD dwAttrId,\
#define PCSCv2_PART10_PROPERTY_bMaxPINSize 7
#define PCSCv2_PART10_PROPERTY_sFirmwareID 8
#define PCSCv2_PART10_PROPERTY_bPPDUSupport 9
#define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10
#define PCSCv2_PART10_PROPERTY_wIdVendor 11
#define PCSCv2_PART10_PROPERTY_wIdProduct 12

/* structures used (but not defined) in PCSC Part 10:
* "IFDs with Secure Pin Entry Capabilities" */
Expand Down
1 change: 1 addition & 0 deletions src/libopensc/libopensc.exports
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ sc_print_path
sc_put_data
sc_read_binary
sc_read_record
sc_reader_can_handle_pin
sc_release_context
sc_reset
sc_reset_retry_counter
Expand Down
5 changes: 5 additions & 0 deletions src/libopensc/opensc.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ struct sc_reader_driver {
#define SC_READER_CARD_INUSE 0x00000004
#define SC_READER_CARD_EXCLUSIVE 0x00000008
#define SC_READER_HAS_WAITING_AREA 0x00000010
#define SC_READER_AUTO_PIN_PAD 0x00000020

/* reader capabilities */
#define SC_READER_CAP_DISPLAY 0x00000001
Expand Down Expand Up @@ -454,6 +455,10 @@ struct sc_reader_operations {
int (*reset)(struct sc_reader *, int);
/* Used to pass in PC/SC handles to minidriver */
int (*use_reader)(struct sc_context *ctx, void *pcsc_context_handle, void *pcsc_card_handle);

/* Get vendor and product identifiers */
int (*get_vendor_product)(struct sc_reader *reader, int *id_vendor,
int *id_product);
};

/*
Expand Down
14 changes: 7 additions & 7 deletions src/libopensc/pkcs15-pin.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ static int _validate_pin(struct sc_pkcs15_card *p15card,
return SC_ERROR_BUFFER_TOO_SMALL;

/* if we use pinpad, no more checks are needed */
if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD)
if (sc_reader_can_handle_pin(p15card->card->reader, auth_info))
return SC_SUCCESS;

/* If pin is given, make sure it is within limits */
Expand Down Expand Up @@ -345,7 +345,7 @@ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card,
data.pin_reference = skey_info->key_reference;
}

if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
if(sc_reader_can_handle_pin(p15card->card->reader, auth_info)) {
if (!pincode && !pinlen)
data.flags |= SC_PIN_CMD_USE_PINPAD;
if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)
Expand Down Expand Up @@ -437,7 +437,7 @@ int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card,
}

if((!oldpin || !newpin)
&& p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
&& sc_reader_can_handle_pin(p15card->card->reader, auth_info)) {
data.flags |= SC_PIN_CMD_USE_PINPAD;
if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
data.pin1.prompt = "Please enter SO PIN";
Expand Down Expand Up @@ -552,7 +552,7 @@ int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card,
break;
}

if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
if(sc_reader_can_handle_pin(p15card->card->reader, auth_info)) {
data.flags |= SC_PIN_CMD_USE_PINPAD;
if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
data.pin1.prompt = "Please enter PUK";
Expand Down Expand Up @@ -648,15 +648,15 @@ int sc_pkcs15_pincache_revalidate(struct sc_pkcs15_card *p15card, const sc_pkcs1
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
}

if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD)
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;

r = sc_pkcs15_find_pin_by_auth_id(p15card, &obj->auth_id, &pin_obj);
if (r != SC_SUCCESS) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Could not find pin object for auth_id %s", sc_pkcs15_print_id(&obj->auth_id));
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
}

if (sc_reader_can_handle_pin(p15card->card->reader, pin_obj->data))
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;

if (pin_obj->usage_counter >= p15card->opts.pin_cache_counter) {
sc_pkcs15_free_object_content(pin_obj);
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
Expand Down
73 changes: 73 additions & 0 deletions src/libopensc/quirks-reader.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* quirks-reader.c: Reader quirks
*
* Copyright (C) 2014 Javier Serrano Polo <javier@jasp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include "config.h"

#include <string.h>

#include "log.h"
#include "opensc.h"
#include "pkcs15.h"
#include "quirks-reader.h"

static int _vendor_specific_problem(struct sc_reader *reader,
struct sc_pkcs15_auth_info *pkcs15_pin_info)
{
int id_vendor;
int id_product;

if (!reader->ops || !reader->ops->get_vendor_product)
return 0;

if (reader->ops->get_vendor_product(reader, &id_vendor, &id_product) != SC_SUCCESS)
return 0;

/* Dell Smart Card Reader Keyboard */
if (id_vendor == 0x413c && id_product == 0x2101
&& !(pkcs15_pin_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING))
return 1;

return 0;
}

int sc_reader_can_handle_pin(struct sc_reader *reader,
struct sc_pkcs15_auth_info *pkcs15_pin_info)
{
struct sc_context *ctx = reader->ctx;

if (!(reader->capabilities & SC_READER_CAP_PIN_PAD))
return 0;

if (!(reader->flags & SC_READER_AUTO_PIN_PAD))
return 1;

if (!pkcs15_pin_info)
return 1;

if (pkcs15_pin_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
return 1;

if (_vendor_specific_problem(reader, pkcs15_pin_info)) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "reader cannot handle this PIN");
return 0;
}

return 1;
}
38 changes: 38 additions & 0 deletions src/libopensc/quirks-reader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* quirks-reader.h: Reader quirks header file
*
* Copyright (C) 2014 Javier Serrano Polo <javier@jasp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#ifndef _OPENSC_QUIRKS_READER_H
#define _OPENSC_QUIRKS_READER_H

#ifdef __cplusplus
extern "C" {
#endif

struct sc_pkcs15_auth_info;
struct sc_reader;

int sc_reader_can_handle_pin(struct sc_reader *reader,
struct sc_pkcs15_auth_info *pkcs15_pin_info);

#ifdef __cplusplus
}
#endif

#endif
67 changes: 65 additions & 2 deletions src/libopensc/reader-pcsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct pcsc_global_private_data {
SCARDCONTEXT pcsc_ctx;
SCARDCONTEXT pcsc_wait_ctx;
int enable_pinpad;
int enable_pinpad_auto;
int enable_pace;
int connect_exclusive;
DWORD disconnect_action;
Expand Down Expand Up @@ -640,13 +641,16 @@ static int pcsc_init(sc_context_t *ctx)
gpriv->transaction_end_action = SCARD_LEAVE_CARD;
gpriv->reconnect_action = SCARD_LEAVE_CARD;
gpriv->enable_pinpad = 1;
gpriv->enable_pinpad_auto = 1;
gpriv->enable_pace = 1;
gpriv->provider_library = DEFAULT_PCSC_PROVIDER;
gpriv->pcsc_ctx = -1;
gpriv->pcsc_wait_ctx = -1;

conf_block = sc_get_conf_block(ctx, "reader_driver", "pcsc", 1);
if (conf_block) {
int not_default;

gpriv->connect_exclusive =
scconf_get_bool(conf_block, "connect_exclusive", gpriv->connect_exclusive);
gpriv->disconnect_action =
Expand All @@ -655,15 +659,19 @@ static int pcsc_init(sc_context_t *ctx)
pcsc_reset_action(scconf_get_str(conf_block, "transaction_end_action", "leave"));
gpriv->reconnect_action =
pcsc_reset_action(scconf_get_str(conf_block, "reconnect_action", "leave"));
not_default =
scconf_get_bool(conf_block, "enable_pinpad", !gpriv->enable_pinpad);
gpriv->enable_pinpad =
scconf_get_bool(conf_block, "enable_pinpad", gpriv->enable_pinpad);
gpriv->enable_pinpad_auto =
gpriv->enable_pinpad != not_default;
gpriv->enable_pace =
scconf_get_bool(conf_block, "enable_pace", gpriv->enable_pace);
gpriv->provider_library =
scconf_get_str(conf_block, "provider_library", gpriv->provider_library);
}
sc_log(ctx, "PC/SC options: connect_exclusive=%d disconnect_action=%d transaction_end_action=%d reconnect_action=%d enable_pinpad=%d enable_pace=%d",
gpriv->connect_exclusive, gpriv->disconnect_action, gpriv->transaction_end_action, gpriv->reconnect_action, gpriv->enable_pinpad, gpriv->enable_pace);
sc_log(ctx, "PC/SC options: connect_exclusive=%d disconnect_action=%d transaction_end_action=%d reconnect_action=%d enable_pinpad=%d enable_pinpad_auto=%d enable_pace=%d",
gpriv->connect_exclusive, gpriv->disconnect_action, gpriv->transaction_end_action, gpriv->reconnect_action, gpriv->enable_pinpad, gpriv->enable_pinpad_auto, gpriv->enable_pace);

gpriv->dlhandle = sc_dlopen(gpriv->provider_library);
if (gpriv->dlhandle == NULL) {
Expand Down Expand Up @@ -895,6 +903,9 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
}
}

if (priv->gpriv->enable_pinpad_auto)
reader->flags |= SC_READER_AUTO_PIN_PAD;

/* Detect display */
if (priv->pin_properties_ioctl) {
rcount = sizeof(rbuf);
Expand Down Expand Up @@ -1940,6 +1951,54 @@ pcsc_perform_pace(struct sc_reader *reader, void *input_pace, void *output_pace)
return SC_SUCCESS;
}

static int part10_get_vendor_product(struct sc_reader *reader, int *id_vendor,
int *id_product)
{
int r;
unsigned char buffer[256];
size_t length = sizeof buffer;
struct pcsc_private_data *priv;

if (!reader)
return SC_ERROR_INVALID_ARGUMENTS;

priv = GET_PRIV_DATA(reader);
if (!priv)
return SC_ERROR_INVALID_ARGUMENTS;

r = pcsc_internal_transmit(reader, NULL, 0, buffer, &length,
priv->get_tlv_properties);
SC_TEST_RET(reader->ctx, SC_LOG_DEBUG_NORMAL, r,
"PC/SC v2 part 10: Get TLV properties failed!");

*id_vendor = part10_find_property_by_tag(buffer, length,
PCSCv2_PART10_PROPERTY_wIdVendor);
*id_product = part10_find_property_by_tag(buffer, length,
PCSCv2_PART10_PROPERTY_wIdProduct);

sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "id_vendor=%04x id_product=%04x", *id_vendor, *id_product);

return SC_SUCCESS;
}

static int pcsc_get_vendor_product(struct sc_reader *reader, int *id_vendor,
int *id_product)
{
int r;
int this_id_vendor = -1;
int this_id_product = -1;

r = part10_get_vendor_product(reader, &this_id_vendor, &this_id_product);

if (id_vendor)
*id_vendor = this_id_vendor;

if (id_product)
*id_product = this_id_product;

return r;
}

struct sc_reader_driver * sc_get_pcsc_driver(void)
{
pcsc_ops.init = pcsc_init;
Expand All @@ -1958,6 +2017,7 @@ struct sc_reader_driver * sc_get_pcsc_driver(void)
pcsc_ops.reset = pcsc_reset;
pcsc_ops.use_reader = NULL;
pcsc_ops.perform_pace = pcsc_perform_pace;
pcsc_ops.get_vendor_product = pcsc_get_vendor_product;

return &pcsc_drv;
}
Expand Down Expand Up @@ -2259,6 +2319,9 @@ int cardmod_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcs
}
}

if (priv->gpriv->enable_pinpad_auto)
reader->flags |= SC_READER_AUTO_PIN_PAD;

if (display_ioctl)
{
rcount = sizeof(rbuf);
Expand Down
11 changes: 6 additions & 5 deletions src/pkcs11/framework-pkcs15.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "libopensc/log.h"
#include "libopensc/asn1.h"
#include "libopensc/cardctl.h"
#include "libopensc/quirks-reader.h"

#include "sc-pkcs11.h"
#ifdef USE_PKCS15_INIT
Expand Down Expand Up @@ -935,9 +936,6 @@ pkcs15_init_slot(struct sc_pkcs15_card *p15card, struct sc_pkcs11_slot *slot,
if (auth != NULL)
slot->token_info.flags |= CKF_USER_PIN_INITIALIZED;

if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD)
slot->token_info.flags |= CKF_PROTECTED_AUTHENTICATION_PATH;

if (p15card->card->caps & SC_CARD_CAP_RNG && p15card->card->ops->get_challenge != NULL)
slot->token_info.flags |= CKF_RNG;

Expand All @@ -963,6 +961,9 @@ pkcs15_init_slot(struct sc_pkcs15_card *p15card, struct sc_pkcs11_slot *slot,
}
strcpy_bp(slot->token_info.label, label, 32);

if (sc_reader_can_handle_pin(p15card->card->reader, pin_info))
slot->token_info.flags |= CKF_PROTECTED_AUTHENTICATION_PATH;

if (pin_info) {
slot->token_info.ulMaxPinLen = pin_info->attrs.pin.max_length;
slot->token_info.ulMinPinLen = pin_info->attrs.pin.min_length;
Expand Down Expand Up @@ -1479,7 +1480,7 @@ pkcs15_login(struct sc_pkcs11_slot *slot, CK_USER_TYPE userType,
if (pin_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
return CKR_FUNCTION_REJECTED;

if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
if (sc_reader_can_handle_pin(p11card->card->reader, pin_info)) {
/* pPin should be NULL in case of a pin pad reader, but
* some apps (e.g. older Netscapes) don't know about it.
* So we don't require that pPin == NULL, but set it to
Expand Down Expand Up @@ -1652,7 +1653,7 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot,
return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_SetPin");

sc_log(context, "Change '%s' (ref:%i,type:%i)", pin_obj->label, auth_info->attrs.pin.reference, login_user);
if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
if (sc_reader_can_handle_pin(p11card->card->reader, auth_info)) {
/* pPin should be NULL in case of a pin pad reader, but
* some apps (e.g. older Netscapes) don't know about it.
* So we don't require that pPin == NULL, but set it to
Expand Down

0 comments on commit 83142d4

Please sign in to comment.