2015-04-25 21:29:03 +00:00
|
|
|
|
/*
|
2011-04-12 07:40:12 +00:00
|
|
|
|
* minidriver.c: OpenSC minidriver
|
2010-02-05 13:05:25 +00:00
|
|
|
|
*
|
2011-04-12 07:40:12 +00:00
|
|
|
|
* Copyright (C) 2009,2010 francois.leblanc@cev-sa.com
|
2015-04-26 17:54:09 +00:00
|
|
|
|
* Copyright (C) 2015 vincent.letoux@mysmartlogon.com
|
2010-02-05 13:05:25 +00:00
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
2011-04-12 07:40:12 +00:00
|
|
|
|
* This module requires "cardmod.h" from CNG SDK or platform SDK to build.
|
2010-02-05 13:05:25 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2011-04-12 07:40:12 +00:00
|
|
|
|
#include "config.h"
|
|
|
|
|
#ifdef ENABLE_MINIDRIVER
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
#ifdef _MANAGED
|
|
|
|
|
#pragma managed(push, off)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2012-05-31 14:40:36 +00:00
|
|
|
|
#include <time.h>
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2010-03-04 08:14:36 +00:00
|
|
|
|
#include <windows.h>
|
2011-01-20 12:58:39 +00:00
|
|
|
|
#include "cardmod.h"
|
2010-03-04 08:14:36 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
#include "libopensc/asn1.h"
|
2011-03-25 18:19:28 +00:00
|
|
|
|
#include "libopensc/cardctl.h"
|
2010-03-04 08:14:36 +00:00
|
|
|
|
#include "libopensc/opensc.h"
|
|
|
|
|
#include "libopensc/pkcs15.h"
|
2010-03-09 07:41:28 +00:00
|
|
|
|
#include "libopensc/log.h"
|
2011-04-07 16:58:01 +00:00
|
|
|
|
#include "libopensc/internal.h"
|
2016-04-06 16:20:36 +00:00
|
|
|
|
#include "libopensc/aux-data.h"
|
2012-05-31 14:40:36 +00:00
|
|
|
|
#include "pkcs15init/pkcs15-init.h"
|
|
|
|
|
|
|
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
|
#include <openssl/opensslv.h>
|
|
|
|
|
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
|
|
|
|
#include <openssl/pem.h>
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2010-03-04 08:14:36 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
|
|
|
|
/* Part of the build svn project in the include directory */
|
|
|
|
|
#include "cardmod-mingw-compat.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-04-19 17:51:22 +00:00
|
|
|
|
/* store the instance given at DllMain when attached to access internal resources */
|
|
|
|
|
HINSTANCE g_inst;
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
#define MD_MINIMUM_VERSION_SUPPORTED 4
|
|
|
|
|
#define MD_CURRENT_VERSION_SUPPORTED 7
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
#define NULLSTR(a) (a == NULL ? "<NULL>" : a)
|
|
|
|
|
#define NULLWSTR(a) (a == NULL ? L"<NULL>" : a)
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
#define MD_MAX_KEY_CONTAINERS 12
|
|
|
|
|
#define MD_CARDID_SIZE 16
|
|
|
|
|
|
|
|
|
|
#define MD_UTC_TIME_LENGTH_MAX 16
|
|
|
|
|
#define MD_CARDCF_LENGTH (sizeof(CARD_CACHE_FILE_FORMAT))
|
|
|
|
|
|
|
|
|
|
#define MD_DATA_APPLICAITON_NAME "CSP"
|
|
|
|
|
#define MD_DATA_DEFAULT_CONT_LABEL "Default Key Container"
|
|
|
|
|
|
|
|
|
|
#define MD_KEY_USAGE_KEYEXCHANGE \
|
|
|
|
|
SC_PKCS15INIT_X509_KEY_ENCIPHERMENT | \
|
|
|
|
|
SC_PKCS15INIT_X509_DATA_ENCIPHERMENT | \
|
|
|
|
|
SC_PKCS15INIT_X509_DIGITAL_SIGNATURE
|
2015-09-25 20:22:29 +00:00
|
|
|
|
#define MD_KEY_USAGE_KEYEXCHANGE_ECC \
|
|
|
|
|
SC_PKCS15INIT_X509_KEY_AGREEMENT| \
|
|
|
|
|
SC_PKCS15INIT_X509_DIGITAL_SIGNATURE
|
2012-05-31 14:40:36 +00:00
|
|
|
|
#define MD_KEY_USAGE_SIGNATURE \
|
|
|
|
|
SC_PKCS15INIT_X509_DIGITAL_SIGNATURE | \
|
|
|
|
|
SC_PKCS15INIT_X509_KEY_CERT_SIGN | \
|
|
|
|
|
SC_PKCS15INIT_X509_CRL_SIGN
|
|
|
|
|
#define MD_KEY_ACCESS \
|
|
|
|
|
SC_PKCS15_PRKEY_ACCESS_SENSITIVE | \
|
|
|
|
|
SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | \
|
|
|
|
|
SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | \
|
|
|
|
|
SC_PKCS15_PRKEY_ACCESS_LOCAL
|
|
|
|
|
|
|
|
|
|
/* copied from pkcs15-cardos.c */
|
|
|
|
|
#define USAGE_ANY_SIGN (SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)
|
|
|
|
|
#define USAGE_ANY_DECIPHER (SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP)
|
2015-09-25 20:22:29 +00:00
|
|
|
|
#define USAGE_ANY_AGREEMENT (SC_PKCS15_PRKEY_USAGE_DERIVE)
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2010-02-17 07:51:52 +00:00
|
|
|
|
/* if use of internal-winscard.h */
|
|
|
|
|
#ifndef SCARD_E_INVALID_PARAMETER
|
2012-05-31 14:40:36 +00:00
|
|
|
|
#define SCARD_E_INVALID_PARAMETER 0x80100004L
|
|
|
|
|
#define SCARD_E_UNSUPPORTED_FEATURE 0x80100022L
|
|
|
|
|
#define SCARD_E_NO_MEMORY 0x80100006L
|
|
|
|
|
#define SCARD_W_WRONG_CHV 0x8010006BL
|
|
|
|
|
#define SCARD_E_FILE_NOT_FOUND 0x80100024L
|
|
|
|
|
#define SCARD_E_UNKNOWN_CARD 0x8010000DL
|
|
|
|
|
#define SCARD_F_UNKNOWN_ERROR 0x80100014L
|
2010-02-17 07:51:52 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2015-04-19 17:51:22 +00:00
|
|
|
|
/* defined twice: in versioninfo-minidriver.rc.in and in minidriver.c */
|
|
|
|
|
#define IDD_PINPAD 101
|
2015-05-02 21:44:05 +00:00
|
|
|
|
#define IDI_LOGO 102
|
2015-04-19 17:51:22 +00:00
|
|
|
|
#define IDC_PINPAD_TEXT 1001
|
|
|
|
|
#define IDC_PINPAD_ICON 1000
|
|
|
|
|
|
2015-04-20 21:25:57 +00:00
|
|
|
|
/* magic to determine previous pinpad authentication */
|
|
|
|
|
#define MAGIC_SESSION_PIN "opensc-minidriver"
|
2015-04-19 17:51:22 +00:00
|
|
|
|
|
2015-10-14 20:48:41 +00:00
|
|
|
|
#define TLS1_0_PROTOCOL_VERSION 0x0301
|
|
|
|
|
#define TLS1_1_PROTOCOL_VERSION 0x0302
|
|
|
|
|
#define TLS1_2_PROTOCOL_VERSION 0x0303
|
|
|
|
|
#define TLS_DERIVE_KEY_SIZE 48
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct md_directory {
|
|
|
|
|
unsigned char name[9];
|
|
|
|
|
|
|
|
|
|
CARD_DIRECTORY_ACCESS_CONDITION acl;
|
|
|
|
|
|
|
|
|
|
struct md_file *files;
|
|
|
|
|
struct md_directory *subdirs;
|
|
|
|
|
|
|
|
|
|
struct md_directory *next;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct md_file {
|
|
|
|
|
unsigned char name[9];
|
|
|
|
|
|
|
|
|
|
CARD_FILE_ACCESS_CONDITION acl;
|
|
|
|
|
|
|
|
|
|
unsigned char *blob;
|
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
|
|
struct md_file *next;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct md_pkcs15_container {
|
|
|
|
|
int index;
|
|
|
|
|
struct sc_pkcs15_id id;
|
|
|
|
|
char guid[MAX_CONTAINER_NAME_LEN + 1];
|
2016-04-06 16:20:36 +00:00
|
|
|
|
unsigned char flags;
|
2015-04-25 21:29:03 +00:00
|
|
|
|
size_t size_key_exchange, size_sign;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
struct sc_pkcs15_object *cert_obj, *prkey_obj, *pubkey_obj;
|
2016-04-06 16:20:36 +00:00
|
|
|
|
// BOOL guid_overwrite;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
};
|
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
struct md_dh_agreement {
|
|
|
|
|
DWORD dwSize;
|
|
|
|
|
PBYTE pbAgreement;
|
|
|
|
|
};
|
|
|
|
|
|
2015-10-11 13:20:04 +00:00
|
|
|
|
struct md_guid_conversion {
|
|
|
|
|
CHAR szOpenSCGuid[MAX_CONTAINER_NAME_LEN+1];
|
|
|
|
|
CHAR szWindowsGuid[MAX_CONTAINER_NAME_LEN+1];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define MD_MAX_CONVERSIONS 50
|
|
|
|
|
struct md_guid_conversion md_static_conversions[MD_MAX_CONVERSIONS] = {0};
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
typedef struct _VENDOR_SPECIFIC
|
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct sc_pkcs15_object *obj_user_pin, *obj_sopin;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct sc_context *ctx;
|
|
|
|
|
struct sc_reader *reader;
|
|
|
|
|
struct sc_card *card;
|
|
|
|
|
struct sc_pkcs15_card *p15card;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct md_pkcs15_container p15_containers[MD_MAX_KEY_CONTAINERS];
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct md_directory root;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
SCARDCONTEXT hSCardCtx;
|
|
|
|
|
SCARDHANDLE hScard;
|
2013-09-24 16:07:03 +00:00
|
|
|
|
|
|
|
|
|
/* These will be used in CardAuthenticateEx to display a dialog box when doing
|
|
|
|
|
* external PIN verification.
|
|
|
|
|
*/
|
|
|
|
|
HWND hwndParent;
|
|
|
|
|
LPWSTR wszPinContext;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
/* these will be used to store intermediate dh agreements results */
|
|
|
|
|
struct md_dh_agreement* dh_agreements;
|
|
|
|
|
BYTE allocatedAgreements;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}VENDOR_SPECIFIC;
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/*
|
2016-05-12 11:15:31 +00:00
|
|
|
|
* Windows (ex. Vista) may access the card from more than one thread.
|
|
|
|
|
* The following data type and static data is an attempt to resolve
|
2012-05-31 14:40:36 +00:00
|
|
|
|
* some of the encountered multi-thread issues of OpenSC
|
|
|
|
|
* on the minidriver side.
|
|
|
|
|
*
|
|
|
|
|
* TODO: resolve multi-thread issues on the OpenSC side
|
|
|
|
|
*/
|
2013-12-29 11:54:36 +00:00
|
|
|
|
#define MD_STATIC_FLAG_READ_ONLY 1
|
|
|
|
|
#define MD_STATIC_FLAG_SUPPORTS_X509_ENROLLMENT 2
|
|
|
|
|
#define MD_STATIC_FLAG_CONTEXT_DELETED 4
|
|
|
|
|
#define MD_STATIC_FLAG_GUID_AS_ID 8
|
|
|
|
|
#define MD_STATIC_FLAG_GUID_AS_LABEL 16
|
|
|
|
|
#define MD_STATIC_FLAG_CREATE_CONTAINER_KEY_IMPORT 32
|
|
|
|
|
#define MD_STATIC_FLAG_CREATE_CONTAINER_KEY_GEN 64
|
2013-12-25 22:18:29 +00:00
|
|
|
|
#define MD_STATIC_FLAG_IGNORE_PIN_LENGTH 128
|
2013-12-29 11:46:51 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
#define MD_STATIC_PROCESS_ATTACHED 0xA11AC4EDL
|
|
|
|
|
struct md_opensc_static_data {
|
|
|
|
|
unsigned flags, flags_checked;
|
|
|
|
|
unsigned long attach_check;
|
|
|
|
|
};
|
|
|
|
|
static struct md_opensc_static_data md_static_data;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define C_ASN1_MD_CONTAINER_ATTRS_SIZE 7
|
|
|
|
|
static const struct sc_asn1_entry c_asn1_md_container_attrs[C_ASN1_MD_CONTAINER_ATTRS_SIZE] = {
|
|
|
|
|
{ "index", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
|
|
|
|
|
{ "id", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_EMPTY_ALLOWED, NULL, NULL },
|
|
|
|
|
{ "guid", SC_ASN1_UTF8STRING, SC_ASN1_TAG_UTF8STRING, SC_ASN1_EMPTY_ALLOWED, NULL, NULL },
|
|
|
|
|
{ "flags", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL },
|
|
|
|
|
{ "sizeKeyExchange", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
|
|
|
|
|
{ "sizeSign", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
|
|
|
|
|
{ NULL, 0, 0, 0, NULL, NULL }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define C_ASN1_MD_CONTAINER_SIZE 2
|
|
|
|
|
static const struct sc_asn1_entry c_asn1_md_container[C_ASN1_MD_CONTAINER_SIZE] = {
|
|
|
|
|
{ "mdContainer", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
|
|
|
|
|
{ NULL, 0, 0, 0, NULL, NULL }
|
|
|
|
|
};
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
static int associate_card(PCARD_DATA pCardData);
|
|
|
|
|
static int disassociate_card(PCARD_DATA pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
static DWORD md_get_cardcf(PCARD_DATA pCardData, CARD_CACHE_FILE_FORMAT **out);
|
|
|
|
|
static DWORD md_pkcs15_delete_object(PCARD_DATA pCardData, struct sc_pkcs15_object *obj);
|
|
|
|
|
static DWORD md_fs_init(PCARD_DATA pCardData);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
static void logprintf(PCARD_DATA pCardData, int level, _Printf_format_string_ const char* format, ...)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
|
|
|
|
va_list arg;
|
2010-02-17 07:51:52 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
/* Use a simplied log to get all messages including messages
|
2011-02-09 17:52:00 +00:00
|
|
|
|
* before opensc is loaded. The file must be modifiable by all
|
2011-04-12 07:40:12 +00:00
|
|
|
|
* users as we maybe called under lsa or user. Note data from
|
2011-02-09 17:52:00 +00:00
|
|
|
|
* multiple process and threads may get intermingled.
|
|
|
|
|
* flush to get last message before ann crash
|
|
|
|
|
* close so as the file is not left open during any wait.
|
|
|
|
|
*/
|
2016-04-13 12:28:06 +00:00
|
|
|
|
DWORD md_debug = 0;
|
2016-06-05 01:04:20 +00:00
|
|
|
|
size_t sz = sizeof(md_debug);
|
2016-04-13 12:28:06 +00:00
|
|
|
|
int rv;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2016-04-13 12:28:06 +00:00
|
|
|
|
rv = sc_ctx_win32_get_config_value("CARDMOD_LOW_LEVEL_DEBUG",
|
|
|
|
|
"MiniDriverDebug", "Software\\OpenSC Project\\OpenSC",
|
|
|
|
|
(char *)(&md_debug), &sz);
|
|
|
|
|
if (rv == SC_SUCCESS && md_debug != 0) {
|
|
|
|
|
FILE *lldebugfp = fopen("C:\\tmp\\md.log","a+");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (lldebugfp) {
|
2011-02-09 17:52:00 +00:00
|
|
|
|
va_start(arg, format);
|
|
|
|
|
vfprintf(lldebugfp, format, arg);
|
|
|
|
|
va_end(arg);
|
|
|
|
|
fflush(lldebugfp);
|
|
|
|
|
fclose(lldebugfp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-17 07:51:52 +00:00
|
|
|
|
va_start(arg, format);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(pCardData != NULL) {
|
2010-02-17 07:51:52 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(vs != NULL && vs->ctx != NULL) {
|
2011-01-20 13:02:50 +00:00
|
|
|
|
#ifdef _MSC_VER
|
2011-05-08 08:07:03 +00:00
|
|
|
|
sc_do_log_noframe(vs->ctx, level, format, arg);
|
2011-01-20 13:02:50 +00:00
|
|
|
|
#else
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/* FIXME: trouble in vsprintf with %S arg under mingw32 */
|
2010-09-23 11:57:51 +00:00
|
|
|
|
if(vs->ctx->debug>=level) {
|
|
|
|
|
vfprintf(vs->ctx->debug_file, format, arg);
|
|
|
|
|
}
|
2011-01-20 13:02:50 +00:00
|
|
|
|
#endif
|
2010-02-17 07:51:52 +00:00
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2010-02-17 07:51:52 +00:00
|
|
|
|
va_end(arg);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-04-25 21:29:03 +00:00
|
|
|
|
static void loghex(PCARD_DATA pCardData, int level, PBYTE data, size_t len)
|
2011-02-09 17:52:00 +00:00
|
|
|
|
{
|
|
|
|
|
char line[74];
|
|
|
|
|
char *c;
|
2015-10-10 17:01:14 +00:00
|
|
|
|
unsigned int i, a;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
unsigned char * p;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, level, "--- %p:%d\n", data, len);
|
|
|
|
|
|
|
|
|
|
if (data == NULL || len <= 0) return;
|
|
|
|
|
|
|
|
|
|
p = data;
|
|
|
|
|
c = line;
|
|
|
|
|
i = 0;
|
|
|
|
|
a = 0;
|
|
|
|
|
memset(line, 0, sizeof(line));
|
|
|
|
|
|
|
|
|
|
while(i < len) {
|
2015-10-10 12:15:23 +00:00
|
|
|
|
sprintf_s(c, sizeof(line)-(size_t)(c-line),"%02X", *p);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
p++;
|
|
|
|
|
c += 2;
|
|
|
|
|
i++;
|
|
|
|
|
if (i%32 == 0) {
|
|
|
|
|
logprintf(pCardData, level, " %04X %s\n", a, line);
|
|
|
|
|
a +=32;
|
|
|
|
|
memset(line, 0, sizeof(line));
|
|
|
|
|
c = line;
|
|
|
|
|
} else {
|
|
|
|
|
if (i%4 == 0) *(c++) = ' ';
|
|
|
|
|
if (i%16 == 0) *(c++) = ' ';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (i%32 != 0)
|
|
|
|
|
logprintf(pCardData, level, " %04X %s\n", a, line);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
static void print_werror(PCARD_DATA pCardData, PSTR str)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
|
|
|
|
void *buf;
|
2015-04-17 19:39:41 +00:00
|
|
|
|
FormatMessageA(
|
2012-05-31 14:40:36 +00:00
|
|
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
NULL, GetLastError(), 0, (LPSTR) &buf, 0, NULL);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
logprintf(pCardData, 0, "%s%s\n", str, (PSTR) buf);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
LocalFree(buf);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
/*
|
2011-04-12 07:40:12 +00:00
|
|
|
|
* check if the card has been removed, or the
|
2011-02-09 17:52:00 +00:00
|
|
|
|
* caller has changed the handles.
|
|
|
|
|
* if so, then free up all previous card info
|
|
|
|
|
* and reestablish
|
|
|
|
|
*/
|
2012-05-31 14:40:36 +00:00
|
|
|
|
static int
|
|
|
|
|
check_reader_status(PCARD_DATA pCardData)
|
|
|
|
|
{
|
2015-05-08 13:49:30 +00:00
|
|
|
|
int r = SCARD_S_SUCCESS;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 4, "check_reader_status\n");
|
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
if(!vs)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 7, "pCardData->hSCardCtx:0x%08X hScard:0x%08X\n",
|
|
|
|
|
pCardData->hSCardCtx, pCardData->hScard);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pCardData->hSCardCtx != vs->hSCardCtx || pCardData->hScard != vs->hScard) {
|
|
|
|
|
logprintf (pCardData, 1, "HANDLES CHANGED from 0x%08X 0x%08X\n", vs->hSCardCtx, vs->hScard);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2015-03-28 12:04:41 +00:00
|
|
|
|
/* Basically a mini AcquireContext */
|
2012-05-31 14:40:36 +00:00
|
|
|
|
r = disassociate_card(pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "disassociate_card r = 0x%08X\n", r);
|
|
|
|
|
r = associate_card(pCardData); /* need to check return codes */
|
2015-05-08 13:49:30 +00:00
|
|
|
|
if (r != SCARD_S_SUCCESS)
|
|
|
|
|
return r;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "associate_card r = 0x%08X\n", r);
|
2015-03-28 12:04:41 +00:00
|
|
|
|
/* Rebuild 'soft' fs - in case changed */
|
2012-05-31 14:40:36 +00:00
|
|
|
|
r = md_fs_init(pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "md_fs_init r = 0x%08X\n", r);
|
|
|
|
|
}
|
|
|
|
|
else if (vs->reader) {
|
|
|
|
|
/* This should always work, as BaseCSP should be checking for removal too */
|
2011-02-09 17:52:00 +00:00
|
|
|
|
r = sc_detect_card_presence(vs->reader);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 2, "check_reader_status r=%d flags 0x%08X\n", r, vs->reader->flags);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-05-08 13:49:30 +00:00
|
|
|
|
return r;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
static DWORD
|
|
|
|
|
md_get_pin_by_role(PCARD_DATA pCardData, PIN_ID role, struct sc_pkcs15_object **ret_obj)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
int rv = SC_SUCCESS;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
if (!ret_obj)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
*ret_obj = NULL;
|
|
|
|
|
|
|
|
|
|
if (role == ROLE_USER) {
|
|
|
|
|
if (!vs->obj_user_pin) {
|
|
|
|
|
/* Get 'global' User PIN; if no, get the 'local' one */
|
|
|
|
|
rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_GLOBAL,
|
|
|
|
|
SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, &vs->obj_user_pin);
|
|
|
|
|
if (rv)
|
|
|
|
|
rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL,
|
|
|
|
|
SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, &vs->obj_user_pin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*ret_obj = vs->obj_user_pin;
|
|
|
|
|
}
|
|
|
|
|
else if (role == ROLE_ADMIN) {
|
|
|
|
|
/* Get SO PIN; if no, get the 'global' PUK; if no get the 'local' one */
|
|
|
|
|
if (!vs->obj_sopin) {
|
|
|
|
|
rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_SOPIN,
|
|
|
|
|
SC_PKCS15_PIN_TYPE_FLAGS_SOPIN, NULL, &vs->obj_sopin);
|
|
|
|
|
if (rv)
|
|
|
|
|
rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PUK_GLOBAL,
|
|
|
|
|
SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, &vs->obj_sopin);
|
|
|
|
|
if (rv)
|
|
|
|
|
rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PUK_LOCAL,
|
|
|
|
|
SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, &vs->obj_sopin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*ret_obj = vs->obj_sopin;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 2, "cannot get PIN object: unsupported role\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (rv == SC_SUCCESS) ? SCARD_S_SUCCESS : SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static BOOL
|
2013-12-29 11:53:41 +00:00
|
|
|
|
md_get_config_bool(PCARD_DATA pCardData, char *flag_name, unsigned flag, BOOL ret_default)
|
2012-05-31 14:40:36 +00:00
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2013-12-29 11:53:41 +00:00
|
|
|
|
BOOL ret = ret_default;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
2013-12-29 11:53:41 +00:00
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 2, "Get '%s' option\n", flag_name);
|
|
|
|
|
if (md_static_data.flags_checked & flag) {
|
|
|
|
|
ret = (md_static_data.flags & flag) ? TRUE : FALSE;
|
|
|
|
|
logprintf(pCardData, 2, "Returns checked flag: %s\n", ret ? "TRUE" : "FALSE");
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-11 08:39:02 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
|
2013-12-29 11:53:41 +00:00
|
|
|
|
if (vs->ctx && vs->reader) {
|
2015-10-11 08:39:02 +00:00
|
|
|
|
struct sc_atr atr;
|
|
|
|
|
scconf_block *atrblock;
|
|
|
|
|
atr.len = pCardData->cbAtr;
|
|
|
|
|
memcpy(atr.value, pCardData->pbAtr, atr.len);
|
|
|
|
|
atrblock = _sc_match_atr_block(vs->ctx, NULL, &atr);
|
2013-12-29 11:53:41 +00:00
|
|
|
|
logprintf(pCardData, 2, "Match ATR:\n");
|
2015-10-11 08:39:02 +00:00
|
|
|
|
loghex(pCardData, 3, atr.value, atr.len);
|
2013-12-29 11:53:41 +00:00
|
|
|
|
|
|
|
|
|
if (atrblock)
|
|
|
|
|
ret = scconf_get_bool(atrblock, flag_name, ret_default) ? TRUE : FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
md_static_data.flags_checked |= flag;
|
|
|
|
|
if (ret == TRUE)
|
|
|
|
|
md_static_data.flags |= flag;
|
|
|
|
|
else
|
|
|
|
|
md_static_data.flags &= ~flag;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 2, "Returns '%s' flag '%s', static flags/checked %X/%X\n",
|
|
|
|
|
flag_name, ret ? "TRUE" : "FALSE",
|
|
|
|
|
md_static_data.flags, md_static_data.flags_checked);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 'Write' mode can be enabled from the OpenSC configuration file*/
|
|
|
|
|
static BOOL
|
|
|
|
|
md_is_read_only(PCARD_DATA pCardData)
|
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 2, "Is read-only?\n");
|
2013-12-29 11:54:36 +00:00
|
|
|
|
return md_get_config_bool(pCardData, "md_read_only", MD_STATIC_FLAG_READ_ONLY, TRUE);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-29 11:53:41 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/* 'Write' mode can be enabled from the OpenSC configuration file*/
|
|
|
|
|
static BOOL
|
|
|
|
|
md_is_supports_X509_enrollment(PCARD_DATA pCardData)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
2015-10-11 08:39:02 +00:00
|
|
|
|
BOOL defaultvalue = !md_is_read_only(pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 2, "Is supports X509 enrollment?\n");
|
2015-10-11 08:39:02 +00:00
|
|
|
|
return md_get_config_bool(pCardData, "md_supports_X509_enrollment", MD_STATIC_FLAG_SUPPORTS_X509_ENROLLMENT, defaultvalue);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-29 11:46:51 +00:00
|
|
|
|
|
|
|
|
|
/* Get know if the GUID has to used as ID of crypto objects */
|
2013-12-29 11:41:36 +00:00
|
|
|
|
static BOOL
|
2013-12-29 11:46:51 +00:00
|
|
|
|
md_is_guid_as_id(PCARD_DATA pCardData)
|
2013-12-29 11:41:36 +00:00
|
|
|
|
{
|
|
|
|
|
logprintf(pCardData, 2, "Is GUID has to be used as ID of crypto objects?\n");
|
2013-12-29 11:54:36 +00:00
|
|
|
|
return md_get_config_bool(pCardData, "md_guid_as_id", MD_STATIC_FLAG_GUID_AS_ID, FALSE);
|
2013-12-29 11:41:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-12-29 11:46:51 +00:00
|
|
|
|
/* Get know if the GUID has to used as label of crypto objects */
|
|
|
|
|
static BOOL
|
|
|
|
|
md_is_guid_as_label(PCARD_DATA pCardData)
|
|
|
|
|
{
|
|
|
|
|
logprintf(pCardData, 2, "Is GUID has to be used as label of crypto objects?\n");
|
2013-12-29 11:54:36 +00:00
|
|
|
|
return md_get_config_bool(pCardData, "md_guid_as_label", MD_STATIC_FLAG_GUID_AS_LABEL, FALSE);
|
2013-12-29 11:46:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-12-29 11:53:41 +00:00
|
|
|
|
/* Get know if disabled CARD_CREATE_CONTAINER_KEY_GEN mechanism */
|
|
|
|
|
static BOOL
|
|
|
|
|
md_is_supports_container_key_gen(PCARD_DATA pCardData)
|
|
|
|
|
{
|
|
|
|
|
logprintf(pCardData, 2, "Is supports 'key generation' create_container mechanism?\n");
|
2013-12-29 11:54:36 +00:00
|
|
|
|
return md_get_config_bool(pCardData, "md_supports_container_key_gen", MD_STATIC_FLAG_CREATE_CONTAINER_KEY_GEN, TRUE);
|
2013-12-29 11:53:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Get know if disabled CARD_CREATE_CONTAINER_KEY_IMPORT mechanism */
|
|
|
|
|
static BOOL
|
|
|
|
|
md_is_supports_container_key_import(PCARD_DATA pCardData)
|
|
|
|
|
{
|
|
|
|
|
logprintf(pCardData, 2, "Is supports 'key import' create container mechanism?\n");
|
2013-12-29 11:54:36 +00:00
|
|
|
|
return md_get_config_bool(pCardData, "md_supports_container_key_import", MD_STATIC_FLAG_CREATE_CONTAINER_KEY_IMPORT, TRUE);
|
2013-12-29 11:53:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/* Check if specified PIN has been verified */
|
|
|
|
|
static BOOL
|
|
|
|
|
md_is_pin_set(PCARD_DATA pCardData, DWORD role)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
CARD_CACHE_FILE_FORMAT *cardcf = NULL;
|
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return FALSE;
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
|
|
|
|
|
if (md_get_cardcf(pCardData, &cardcf) != SCARD_S_SUCCESS)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return IS_PIN_SET(cardcf->bPinsFreshness, role);
|
|
|
|
|
}
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
2015-10-10 13:39:27 +00:00
|
|
|
|
|
|
|
|
|
/* generate unique key label (GUID)*/
|
|
|
|
|
static VOID md_generate_guid( __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szGuid) {
|
|
|
|
|
RPC_CSTR szRPCGuid = NULL;
|
|
|
|
|
GUID Label = {0};
|
|
|
|
|
UuidCreate(&Label);
|
|
|
|
|
UuidToStringA(&Label, &szRPCGuid);
|
|
|
|
|
strncpy_s(szGuid, MAX_CONTAINER_NAME_LEN+1, (PSTR) szRPCGuid, MAX_CONTAINER_NAME_LEN);
|
|
|
|
|
if (szRPCGuid) RpcStringFreeA(&szRPCGuid);
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 16:20:36 +00:00
|
|
|
|
static DWORD
|
2015-10-11 13:20:04 +00:00
|
|
|
|
md_contguid_get_guid_from_card(PCARD_DATA pCardData, struct sc_pkcs15_object *prkey, __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szGuid)
|
|
|
|
|
{
|
|
|
|
|
int rv;
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
size_t guid_len = MAX_CONTAINER_NAME_LEN+1;
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
2015-10-11 13:20:04 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
|
2016-04-08 07:53:10 +00:00
|
|
|
|
rv = sc_pkcs15_get_object_guid(vs->p15card, prkey, 1, (unsigned char*) szGuid, &guid_len);
|
2015-10-11 13:20:04 +00:00
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 2, "md_contguid_get_guid_from_card(): error %d\n", rv);
|
2016-04-06 16:20:36 +00:00
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
}
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* add a new entry in the guid conversion table */
|
2016-04-06 16:20:36 +00:00
|
|
|
|
static DWORD
|
|
|
|
|
md_contguid_add_conversion(PCARD_DATA pCardData, struct sc_pkcs15_object *prkey,
|
|
|
|
|
__in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szWindowsGuid)
|
2015-10-11 13:20:04 +00:00
|
|
|
|
{
|
2016-04-06 16:20:36 +00:00
|
|
|
|
DWORD ret;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
int i;
|
|
|
|
|
CHAR szOpenSCGuid[MAX_CONTAINER_NAME_LEN+1] = "";
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
|
|
|
|
ret = md_contguid_get_guid_from_card(pCardData, prkey, szOpenSCGuid);
|
|
|
|
|
if (ret != SCARD_S_SUCCESS)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
if (strcmp(szOpenSCGuid, szWindowsGuid) == 0)
|
|
|
|
|
return ret;
|
|
|
|
|
|
2015-10-11 13:20:04 +00:00
|
|
|
|
for (i = 0; i < MD_MAX_CONVERSIONS; i++) {
|
|
|
|
|
if (md_static_conversions[i].szWindowsGuid[0] == 0) {
|
|
|
|
|
strcpy_s(md_static_conversions[i].szWindowsGuid, MAX_CONTAINER_NAME_LEN+1, szWindowsGuid);
|
|
|
|
|
strcpy_s(md_static_conversions[i].szOpenSCGuid, MAX_CONTAINER_NAME_LEN+1, szOpenSCGuid);
|
|
|
|
|
logprintf(pCardData, 0, "md_contguid_add_conversion(): Registering conversion '%s' '%s'\n", szWindowsGuid, szOpenSCGuid);
|
2016-04-06 16:20:36 +00:00
|
|
|
|
return SCARD_S_SUCCESS;;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-06 16:20:36 +00:00
|
|
|
|
logprintf(pCardData, 0, "md_contguid_add_conversion(): Unable to add a new conversion with guid %s.\n", szWindowsGuid);
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* remove an entry in the guid conversion table*/
|
|
|
|
|
static VOID
|
|
|
|
|
md_contguid_delete_conversion(PCARD_DATA pCardData, __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szWindowsGuid)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < MD_MAX_CONVERSIONS; i++) {
|
|
|
|
|
if (strcmp(md_static_conversions[i].szWindowsGuid,szWindowsGuid) == 0) {
|
|
|
|
|
memset(md_static_conversions + i, 0, sizeof(struct md_guid_conversion));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* this function take the guid in input and search if it should be replaced
|
|
|
|
|
Return if it has been replaced or not */
|
|
|
|
|
static BOOL
|
|
|
|
|
md_contguid_find_conversion(PCARD_DATA pCardData, __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szGuid)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < MD_MAX_CONVERSIONS; i++) {
|
|
|
|
|
if (strcmp(md_static_conversions[i].szOpenSCGuid,szGuid) == 0) {
|
|
|
|
|
strcpy_s(szGuid, MAX_CONTAINER_NAME_LEN+1, md_static_conversions[i].szWindowsGuid);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-10 13:39:27 +00:00
|
|
|
|
/* build key args from the minidriver guid */
|
|
|
|
|
static VOID
|
|
|
|
|
md_contguid_build_key_args_from_cont_guid(PCARD_DATA pCardData, __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szGuid,
|
2016-04-06 16:20:36 +00:00
|
|
|
|
struct sc_pkcs15init_prkeyargs *prkey_args)
|
2015-10-10 13:39:27 +00:00
|
|
|
|
{
|
|
|
|
|
/* strlen(szGuid) <= MAX_CONTAINER_NAME */
|
|
|
|
|
logprintf(pCardData, 3, "Using the guid '%s'\n", szGuid);
|
|
|
|
|
if (szGuid[0] != 0) {
|
|
|
|
|
prkey_args->guid = (unsigned char*) szGuid;
|
|
|
|
|
prkey_args->guid_len = strlen(szGuid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (md_is_guid_as_id(pCardData)) {
|
|
|
|
|
memcpy(prkey_args->id.value, szGuid, strlen(szGuid));
|
|
|
|
|
prkey_args->id.len = strlen(szGuid);
|
|
|
|
|
}
|
|
|
|
|
if (md_is_guid_as_label(pCardData)) {
|
|
|
|
|
prkey_args->label = szGuid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* build minidriver guid from the key */
|
2016-04-06 16:20:36 +00:00
|
|
|
|
static DWORD
|
2015-10-10 13:39:27 +00:00
|
|
|
|
md_contguid_build_cont_guid_from_key(PCARD_DATA pCardData, struct sc_pkcs15_object *key_obj, __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szGuid)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct sc_pkcs15_prkey_info *prkey_info = (struct sc_pkcs15_prkey_info *)key_obj->data;
|
2016-04-06 16:20:36 +00:00
|
|
|
|
DWORD dwret = SCARD_S_SUCCESS;
|
|
|
|
|
|
2015-10-10 13:39:27 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
2015-10-10 13:39:27 +00:00
|
|
|
|
szGuid[0] = '\0';
|
2015-10-11 13:20:04 +00:00
|
|
|
|
/* priorize the use of the key id over the key label as a container name */
|
|
|
|
|
if (md_is_guid_as_id(pCardData) && prkey_info->id.len > 0 && prkey_info->id.len <= MAX_CONTAINER_NAME_LEN) {
|
|
|
|
|
memcpy(szGuid, prkey_info->id.value, prkey_info->id.len);
|
|
|
|
|
szGuid[prkey_info->id.len] = 0;
|
|
|
|
|
} else if (md_is_guid_as_label(pCardData) && key_obj->label[0] != 0) {
|
|
|
|
|
strncpy_s(szGuid, MAX_CONTAINER_NAME_LEN+1, key_obj->label, MAX_CONTAINER_NAME_LEN);
|
2015-10-10 13:39:27 +00:00
|
|
|
|
} else {
|
2016-04-06 16:20:36 +00:00
|
|
|
|
dwret = md_contguid_get_guid_from_card(pCardData, key_obj, szGuid);
|
2015-10-10 13:39:27 +00:00
|
|
|
|
}
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
|
|
|
|
return dwret;
|
2015-10-10 13:39:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_cont_flags_from_key(PCARD_DATA pCardData, struct sc_pkcs15_object *key_obj, unsigned char *cont_flags)
|
|
|
|
|
{
|
|
|
|
|
struct sc_pkcs15_prkey_info *prkey_info = NULL;
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
|
|
|
|
|
prkey_info = (struct sc_pkcs15_prkey_info *)key_obj->data;
|
|
|
|
|
|
|
|
|
|
*cont_flags = CONTAINER_MAP_VALID_CONTAINER;
|
|
|
|
|
if (prkey_info->aux_data) {
|
|
|
|
|
rv = sc_aux_data_get_md_flags(vs->ctx, prkey_info->aux_data, cont_flags);
|
|
|
|
|
if (rv != SC_ERROR_NOT_SUPPORTED && rv != SC_SUCCESS)
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/* Search directory by name and optionally by name of it's parent */
|
|
|
|
|
static DWORD
|
|
|
|
|
md_fs_find_directory(PCARD_DATA pCardData, struct md_directory *parent, char *name, struct md_directory **out)
|
2011-03-23 18:37:46 +00:00
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct md_directory *dir = NULL;
|
|
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
|
*out = NULL;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
2011-04-12 07:40:12 +00:00
|
|
|
|
if (!pCardData)
|
2011-03-23 18:37:46 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
if (!parent)
|
|
|
|
|
parent = &vs->root;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!name) {
|
|
|
|
|
dir = parent;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
dir = parent->subdirs;
|
|
|
|
|
while(dir) {
|
2015-10-06 20:47:50 +00:00
|
|
|
|
if (strlen(name) > sizeof dir->name
|
2015-10-16 07:58:01 +00:00
|
|
|
|
|| !strncmp(dir->name, name, sizeof dir->name))
|
2012-05-31 14:40:36 +00:00
|
|
|
|
break;
|
|
|
|
|
dir = dir->next;
|
|
|
|
|
}
|
2011-03-23 18:37:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!dir)
|
|
|
|
|
return SCARD_E_DIR_NOT_FOUND;
|
|
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
|
*out = dir;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "MD virtual file system: found '%s' directory\n", name);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_fs_add_directory(PCARD_DATA pCardData, struct md_directory **head, char *name,
|
|
|
|
|
CARD_FILE_ACCESS_CONDITION acl,
|
|
|
|
|
struct md_directory **out)
|
|
|
|
|
{
|
|
|
|
|
struct md_directory *new_dir = NULL;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !head || !name)
|
2011-03-23 18:37:46 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
new_dir = pCardData->pfnCspAlloc(sizeof(struct md_directory));
|
|
|
|
|
if (!new_dir)
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
memset(new_dir, 0, sizeof(struct md_directory));
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
2015-10-10 20:07:49 +00:00
|
|
|
|
strncpy_s(new_dir->name, sizeof(new_dir->name), name, sizeof(new_dir->name) - 1);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
new_dir->acl = acl;
|
|
|
|
|
|
|
|
|
|
if (*head == NULL) {
|
|
|
|
|
*head = new_dir;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2015-10-16 07:58:01 +00:00
|
|
|
|
struct md_directory *last = *head;
|
|
|
|
|
while (last->next)
|
|
|
|
|
last = last->next;
|
|
|
|
|
last->next = new_dir;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
|
*out = new_dir;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "MD virtual file system: directory '%s' added\n", name);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_fs_find_file(PCARD_DATA pCardData, char *parent, char *name, struct md_file **out)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct md_file *file = NULL;
|
|
|
|
|
struct md_directory *dir = NULL;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
|
*out = NULL;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !name)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_find_directory(pCardData, NULL, parent, &dir);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "find directory '%s' error: %X\n", parent ? parent : "<null>", dwret);
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
else if (!dir) {
|
|
|
|
|
logprintf(pCardData, 2, "directory '%s' not found\n", parent ? parent : "<null>");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (file = dir->files; file!=NULL;) {
|
2015-10-06 20:47:50 +00:00
|
|
|
|
if (sizeof file->name < strlen(name)
|
|
|
|
|
|| !strncmp(file->name, name, sizeof file->name))
|
2012-05-31 14:40:36 +00:00
|
|
|
|
break;
|
|
|
|
|
file = file->next;
|
|
|
|
|
}
|
|
|
|
|
if (!file)
|
|
|
|
|
return SCARD_E_FILE_NOT_FOUND;
|
|
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
|
*out = file;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "MD virtual file system: found '%s' file\n", name);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_fs_add_file(PCARD_DATA pCardData, struct md_file **head, char *name, CARD_FILE_ACCESS_CONDITION acl,
|
|
|
|
|
unsigned char *blob, size_t size, struct md_file **out)
|
|
|
|
|
{
|
|
|
|
|
struct md_file *new_file = NULL;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !head || !name)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
new_file = pCardData->pfnCspAlloc(sizeof(struct md_file));
|
|
|
|
|
if (!new_file)
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
memset(new_file, 0, sizeof(struct md_file));
|
|
|
|
|
|
2015-10-10 20:07:49 +00:00
|
|
|
|
strncpy_s(new_file->name, sizeof(new_file->name), name, sizeof(new_file->name) - 1);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
new_file->size = size;
|
|
|
|
|
new_file->acl = acl;
|
|
|
|
|
|
|
|
|
|
if (size) {
|
|
|
|
|
new_file->blob = pCardData->pfnCspAlloc(size);
|
|
|
|
|
if (!new_file->blob) {
|
|
|
|
|
pCardData->pfnCspFree(new_file);
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
if (blob)
|
|
|
|
|
CopyMemory(new_file->blob, blob, size);
|
|
|
|
|
else
|
|
|
|
|
memset(new_file->blob, 0, size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*head == NULL) {
|
|
|
|
|
*head = new_file;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2015-10-16 07:58:01 +00:00
|
|
|
|
struct md_file *last = *head;
|
|
|
|
|
while (last->next)
|
|
|
|
|
last = last->next;
|
|
|
|
|
last->next = new_file;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
|
*out = new_file;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "MD virtual file system: file '%s' added\n", name);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
md_fs_free_file(PCARD_DATA pCardData, struct md_file *file)
|
|
|
|
|
{
|
|
|
|
|
if (!file)
|
|
|
|
|
return;
|
|
|
|
|
if (file->blob)
|
|
|
|
|
pCardData->pfnCspFree(file->blob);
|
|
|
|
|
file->blob = NULL;
|
|
|
|
|
file->size = 0;
|
2015-04-12 11:34:18 +00:00
|
|
|
|
pCardData->pfnCspFree(file);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_fs_delete_file(PCARD_DATA pCardData, char *parent, char *name)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct md_file *file = NULL, *file_to_rm = NULL;
|
|
|
|
|
struct md_directory *dir = NULL;
|
|
|
|
|
int deleted = 0;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !name)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_find_directory(pCardData, NULL, parent, &dir);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "find directory '%s' error: %X\n", parent ? parent : "<null>", dwret);
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
else if (!dir) {
|
|
|
|
|
logprintf(pCardData, 2, "directory '%s' not found\n", parent ? parent : "<null>");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
else if (!dir->files) {
|
|
|
|
|
logprintf(pCardData, 2, "no files in '%s' directory\n", parent ? parent : "<null>");
|
|
|
|
|
return SCARD_E_FILE_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-06 20:47:50 +00:00
|
|
|
|
if (sizeof dir->files->name < strlen(name)
|
|
|
|
|
|| !strncmp(dir->files->name, name, sizeof dir->files->name)) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
file_to_rm = dir->files;
|
|
|
|
|
dir->files = dir->files->next;
|
|
|
|
|
md_fs_free_file(pCardData, file_to_rm);
|
|
|
|
|
dwret = SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for (file = dir->files; file!=NULL; file = file->next) {
|
|
|
|
|
if (!file->next)
|
|
|
|
|
break;
|
2015-10-06 20:47:50 +00:00
|
|
|
|
if (sizeof file->next->name < strlen(name)
|
|
|
|
|
|| !strncmp(file->next->name, name, sizeof file->next->name)) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
file_to_rm = file->next;
|
|
|
|
|
file->next = file->next->next;
|
|
|
|
|
md_fs_free_file(pCardData, file_to_rm);
|
|
|
|
|
deleted = 1;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = deleted ? SCARD_S_SUCCESS : SCARD_E_FILE_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcmp(parent, "mscp")) {
|
|
|
|
|
int idx = -1;
|
|
|
|
|
|
2015-10-10 20:07:49 +00:00
|
|
|
|
if(sscanf_s(name, "ksc%d", &idx) > 0) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
2015-10-10 20:07:49 +00:00
|
|
|
|
else if(sscanf_s(name, "kxc%d", &idx) > 0) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (idx >= 0 && idx < MD_MAX_KEY_CONTAINERS) {
|
|
|
|
|
dwret = md_pkcs15_delete_object(pCardData, vs->p15_containers[idx].cert_obj);
|
|
|
|
|
vs->p15_containers[idx].cert_obj = NULL;
|
|
|
|
|
if(dwret != SCARD_S_SUCCESS)
|
|
|
|
|
logprintf(pCardData, 2, "Cannot delete certificate PKCS#15 object #%i: dwret 0x%X\n", idx, dwret);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-12 11:34:18 +00:00
|
|
|
|
static DWORD
|
|
|
|
|
md_fs_finalize(PCARD_DATA pCardData)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct md_file *file = NULL, *file_to_rm;
|
|
|
|
|
struct md_directory *dir = NULL, *dir_to_rm;
|
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
|
|
|
|
|
file = vs->root.files;
|
|
|
|
|
while (file != NULL) {
|
|
|
|
|
file_to_rm = file;
|
|
|
|
|
file = file->next;
|
|
|
|
|
md_fs_free_file(pCardData, file_to_rm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dir = vs->root.subdirs;
|
|
|
|
|
while(dir) {
|
|
|
|
|
file = dir->files;
|
|
|
|
|
while (file != NULL) {
|
|
|
|
|
file_to_rm = file;
|
|
|
|
|
file = file->next;
|
|
|
|
|
md_fs_free_file(pCardData, file_to_rm);
|
|
|
|
|
}
|
|
|
|
|
dir_to_rm = dir;
|
|
|
|
|
dir = dir->next;
|
|
|
|
|
pCardData->pfnCspFree(dir_to_rm);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/*
|
|
|
|
|
* Update 'soft' containers.
|
|
|
|
|
* Called each time when 'WriteFile' is called for 'cmapfile'.
|
|
|
|
|
*/
|
|
|
|
|
static DWORD
|
|
|
|
|
md_pkcs15_update_containers(PCARD_DATA pCardData, unsigned char *blob, size_t size)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
CONTAINER_MAP_RECORD *pp;
|
|
|
|
|
DWORD dwret = SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
int nn_records, idx;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !blob || size < sizeof(CONTAINER_MAP_RECORD))
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
|
2015-04-25 21:29:03 +00:00
|
|
|
|
nn_records = (int) size/sizeof(CONTAINER_MAP_RECORD);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (nn_records > MD_MAX_KEY_CONTAINERS)
|
|
|
|
|
nn_records = MD_MAX_KEY_CONTAINERS;
|
|
|
|
|
|
|
|
|
|
for (idx=0, pp = (CONTAINER_MAP_RECORD *)blob; idx<nn_records; idx++, pp++) {
|
|
|
|
|
struct md_pkcs15_container *cont = &(vs->p15_containers[idx]);
|
|
|
|
|
size_t count;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
CHAR szGuid[MAX_CONTAINER_NAME_LEN+1] = "";
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-10-11 13:20:04 +00:00
|
|
|
|
count = wcstombs(szGuid, pp->wszGuid, sizeof(cont->guid));
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!count) {
|
2015-10-11 13:20:04 +00:00
|
|
|
|
if (cont->guid[0] != 0) {
|
|
|
|
|
md_contguid_delete_conversion(pCardData, cont->guid);
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
memset(cont, 0, sizeof(CONTAINER_MAP_RECORD));
|
|
|
|
|
}
|
2011-03-23 18:37:46 +00:00
|
|
|
|
else {
|
2015-10-11 13:20:04 +00:00
|
|
|
|
strcpy_s(cont->guid,MAX_CONTAINER_NAME_LEN+1, szGuid);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
cont->index = idx;
|
|
|
|
|
cont->flags = pp->bFlags;
|
|
|
|
|
cont->size_sign = pp->wSigKeySizeBits;
|
|
|
|
|
cont->size_key_exchange = pp->wKeyExchangeKeySizeBits;
|
2015-10-06 06:21:20 +00:00
|
|
|
|
logprintf(pCardData, 3, "update P15 containers: touch container (idx:%i,id:%s,guid:%.*s,flags:%X)\n",
|
2016-04-06 16:20:36 +00:00
|
|
|
|
idx, sc_pkcs15_print_id(&cont->id),
|
|
|
|
|
(int)sizeof cont->guid, cont->guid, cont->flags);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_pkcs15_delete_object(PCARD_DATA pCardData, struct sc_pkcs15_object *obj)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct sc_profile *profile = NULL;
|
|
|
|
|
struct sc_card *card = NULL;
|
|
|
|
|
struct sc_app_info *app_info = NULL;
|
|
|
|
|
DWORD dwret = SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
card = vs->p15card->card;
|
|
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2015-10-04 15:33:14 +00:00
|
|
|
|
logprintf(pCardData, 3, "MdDeleteObject('%.*s',type:0x%X) called\n", (int) sizeof obj->label, obj->label, obj->type);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
rv = sc_lock(card);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdDeleteObject(): cannot lock card\n");
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_info = vs->p15card->app;
|
2015-09-30 20:47:16 +00:00
|
|
|
|
rv = sc_pkcs15init_bind(card, "pkcs15", NULL, NULL, &profile);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdDeleteObject(): PKCS#15 bind failed\n");
|
|
|
|
|
sc_unlock(card);
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_finalize_profile(card, profile, app_info ? &app_info->aid : NULL);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdDeleteObject(): cannot finalize profile\n");
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sc_pkcs15init_set_p15card(profile, vs->p15card);
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_delete_object(vs->p15card, profile, obj);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 2, "MdDeleteObject(): pkcs15init delete object failed %d\n", rv);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwret = SCARD_S_SUCCESS;
|
|
|
|
|
logprintf(pCardData, 3, "MdDeleteObject() returns OK\n");
|
|
|
|
|
done:
|
|
|
|
|
sc_pkcs15init_unbind(profile);
|
|
|
|
|
sc_unlock(card);
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set 'soft' file contents,
|
|
|
|
|
* and update data associated to 'cardcf' and 'cmapfile'.
|
|
|
|
|
*/
|
|
|
|
|
static DWORD
|
|
|
|
|
md_fs_set_content(PCARD_DATA pCardData, struct md_file *file, unsigned char *blob, size_t size)
|
|
|
|
|
{
|
|
|
|
|
if (!pCardData || !file)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
if (file->blob)
|
|
|
|
|
pCardData->pfnCspFree(file->blob);
|
|
|
|
|
|
|
|
|
|
file->blob = pCardData->pfnCspAlloc(size);
|
|
|
|
|
if (!file->blob)
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
CopyMemory(file->blob, blob, size);
|
|
|
|
|
file->size = size;
|
|
|
|
|
|
|
|
|
|
if (!strcmp(file->name, "cmapfile"))
|
|
|
|
|
return md_pkcs15_update_containers(pCardData, blob, size);
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set 'cardid' from the 'serialNumber' attribute of the 'tokenInfo'
|
|
|
|
|
*/
|
|
|
|
|
static DWORD
|
|
|
|
|
md_set_cardid(PCARD_DATA pCardData, struct md_file *file)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !file)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
if (vs->p15card->tokeninfo && vs->p15card->tokeninfo->serial_number) {
|
|
|
|
|
unsigned char sn_bin[SC_MAX_SERIALNR];
|
|
|
|
|
unsigned char cardid_bin[MD_CARDID_SIZE];
|
|
|
|
|
size_t offs, wr, sn_len = sizeof(sn_bin);
|
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
|
|
rv = sc_hex_to_bin(vs->p15card->tokeninfo->serial_number, sn_bin, &sn_len);
|
2012-08-22 10:45:03 +00:00
|
|
|
|
if (rv) {
|
|
|
|
|
sn_len = strlen(vs->p15card->tokeninfo->serial_number);
|
|
|
|
|
if (sn_len > SC_MAX_SERIALNR) {
|
|
|
|
|
sn_len = SC_MAX_SERIALNR;
|
|
|
|
|
}
|
|
|
|
|
memcpy(sn_bin, vs->p15card->tokeninfo->serial_number, sn_len);
|
|
|
|
|
}
|
2013-12-29 18:46:30 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
for (offs=0; offs < MD_CARDID_SIZE; ) {
|
|
|
|
|
wr = MD_CARDID_SIZE - offs;
|
|
|
|
|
if (wr > sn_len)
|
|
|
|
|
wr = sn_len;
|
|
|
|
|
memcpy(cardid_bin + offs, sn_bin, wr);
|
|
|
|
|
offs += wr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_set_content(pCardData, file, cardid_bin, MD_CARDID_SIZE);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "cardid(%i)\n", file->size);
|
|
|
|
|
loghex(pCardData, 3, file->blob, file->size);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-09 06:19:51 +00:00
|
|
|
|
/* fill the msroots file from root certificates */
|
2015-04-18 19:43:13 +00:00
|
|
|
|
static void
|
2017-03-09 06:19:51 +00:00
|
|
|
|
md_fs_read_msroots_file(PCARD_DATA pCardData, char *parent, struct md_file *file)
|
2015-04-18 19:43:13 +00:00
|
|
|
|
{
|
|
|
|
|
CERT_BLOB dbStore = {0};
|
|
|
|
|
HCERTSTORE hCertStore = NULL;
|
|
|
|
|
DWORD dwret = 0;
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
int rv, ii, cert_num;
|
|
|
|
|
struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS];
|
|
|
|
|
|
2015-04-25 21:29:03 +00:00
|
|
|
|
hCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, (HCRYPTPROV_LEGACY) NULL, 0, NULL);
|
2015-04-18 19:43:13 +00:00
|
|
|
|
if (!hCertStore) {
|
|
|
|
|
dwret = GetLastError();
|
|
|
|
|
goto Ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC *) pCardData->pvVendorSpecific;
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_CERT_X509, prkey_objs, MD_MAX_KEY_CONTAINERS);
|
|
|
|
|
if (rv < 0) {
|
|
|
|
|
logprintf(pCardData, 0, "certificate enumeration failed: %s\n", sc_strerror(rv));
|
|
|
|
|
goto Ret;
|
|
|
|
|
}
|
|
|
|
|
cert_num = rv;
|
|
|
|
|
for(ii = 0; ii < cert_num; ii++) {
|
|
|
|
|
struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) prkey_objs[ii]->data;
|
|
|
|
|
struct sc_pkcs15_cert *cert = NULL;
|
|
|
|
|
PCCERT_CONTEXT wincert = NULL;
|
|
|
|
|
if (cert_info->authority) {
|
|
|
|
|
rv = sc_pkcs15_read_certificate(vs->p15card, cert_info, &cert);
|
|
|
|
|
if(rv) {
|
|
|
|
|
logprintf(pCardData, 2, "Cannot read certificate idx:%i: sc-error %d\n", ii, rv);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2015-04-25 21:29:03 +00:00
|
|
|
|
wincert = CertCreateCertificateContext(X509_ASN_ENCODING, cert->data.value, (DWORD) cert->data.len);
|
2015-04-18 19:43:13 +00:00
|
|
|
|
if (wincert) {
|
|
|
|
|
CertAddCertificateContextToStore(hCertStore, wincert, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
|
|
|
|
|
CertFreeCertificateContext(wincert);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 2, "unable to load the certificate from windows 0x%08X\n", GetLastError());
|
|
|
|
|
}
|
|
|
|
|
sc_pkcs15_free_certificate(cert);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (FALSE == CertSaveStore( hCertStore,
|
|
|
|
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
|
|
|
|
CERT_STORE_SAVE_AS_PKCS7,
|
|
|
|
|
CERT_STORE_SAVE_TO_MEMORY,
|
|
|
|
|
&dbStore,
|
|
|
|
|
0)) {
|
|
|
|
|
dwret = GetLastError();
|
|
|
|
|
goto Ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbStore.pbData = (PBYTE) pCardData->pfnCspAlloc(dbStore.cbData);
|
|
|
|
|
|
|
|
|
|
if (NULL == dbStore.pbData) {
|
|
|
|
|
dwret = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
goto Ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FALSE == CertSaveStore( hCertStore,
|
|
|
|
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
|
|
|
|
CERT_STORE_SAVE_AS_PKCS7,
|
|
|
|
|
CERT_STORE_SAVE_TO_MEMORY,
|
|
|
|
|
&dbStore,
|
|
|
|
|
0))
|
|
|
|
|
{
|
|
|
|
|
dwret = GetLastError();
|
|
|
|
|
goto Ret;
|
|
|
|
|
}
|
|
|
|
|
file->size = dbStore.cbData;
|
|
|
|
|
file->blob = dbStore.pbData;
|
|
|
|
|
dbStore.pbData = NULL;
|
|
|
|
|
Ret:
|
|
|
|
|
if (dbStore.pbData)
|
|
|
|
|
pCardData->pfnCspFree(dbStore.pbData);
|
|
|
|
|
if (hCertStore)
|
|
|
|
|
CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/*
|
|
|
|
|
* Return content of the 'soft' file.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
md_fs_read_content(PCARD_DATA pCardData, char *parent, struct md_file *file)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct md_directory *dir = NULL;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !file)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_find_directory(pCardData, NULL, parent, &dir);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "find directory '%s' error: %X\n", parent ? parent : "<null>", dwret);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (!dir) {
|
|
|
|
|
logprintf(pCardData, 2, "directory '%s' not found\n", parent ? parent : "<null>");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-05-08 13:49:30 +00:00
|
|
|
|
if (vs->p15card == NULL) {
|
2015-10-03 16:56:19 +00:00
|
|
|
|
return;
|
2015-05-08 13:49:30 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
if (!strcmp(dir->name, "mscp")) {
|
|
|
|
|
int idx, rv;
|
|
|
|
|
|
2015-10-10 20:07:49 +00:00
|
|
|
|
if(sscanf_s(file->name, "ksc%d", &idx) > 0) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
2015-10-10 20:07:49 +00:00
|
|
|
|
else if(sscanf_s(file->name, "kxc%d", &idx) > 0) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
idx = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (idx >=0 && idx < MD_MAX_KEY_CONTAINERS && vs->p15_containers[idx].cert_obj) {
|
|
|
|
|
struct sc_pkcs15_cert *cert = NULL;
|
|
|
|
|
struct sc_pkcs15_object *cert_obj = vs->p15_containers[idx].cert_obj;
|
|
|
|
|
struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *)cert_obj->data;
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15_read_certificate(vs->p15card, cert_info, &cert);
|
|
|
|
|
if(rv) {
|
|
|
|
|
logprintf(pCardData, 2, "Cannot read certificate idx:%i: sc-error %d\n", idx, rv);
|
|
|
|
|
logprintf(pCardData, 2, "set cardcf from 'DATA' pkcs#15 object\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-30 20:38:27 +00:00
|
|
|
|
file->size = cert->data.len;
|
|
|
|
|
file->blob = pCardData->pfnCspAlloc(cert->data.len);
|
|
|
|
|
CopyMemory(file->blob, cert->data.value, cert->data.len);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
sc_pkcs15_free_certificate(cert);
|
|
|
|
|
}
|
2017-03-09 06:19:51 +00:00
|
|
|
|
if (!strcmp(file->name, "msroots")) {
|
|
|
|
|
md_fs_read_msroots_file(pCardData, parent, file);
|
2015-04-18 19:43:13 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set content of 'cardcf',
|
|
|
|
|
* for that look for the possible source in the following order:
|
|
|
|
|
* - data from the dedicated PKCS#15 'DATA' object;
|
|
|
|
|
* - 'lastUpdate' attribute of tokenInfo;
|
|
|
|
|
* - random data.
|
|
|
|
|
*/
|
|
|
|
|
static DWORD
|
|
|
|
|
md_set_cardcf(PCARD_DATA pCardData, struct md_file *file)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
char *last_update = NULL;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
CARD_CACHE_FILE_FORMAT empty = {0};
|
2012-05-31 14:40:36 +00:00
|
|
|
|
size_t empty_len = sizeof(empty);
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !file)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_set_content(pCardData, file, (unsigned char *)(&empty), MD_CARDCF_LENGTH);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "'cardcf' content(%i)\n", file->size);
|
|
|
|
|
loghex(pCardData, 3, file->blob, file->size);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Return content of the 'soft' 'cardcf' file
|
|
|
|
|
*/
|
|
|
|
|
static DWORD
|
|
|
|
|
md_get_cardcf(PCARD_DATA pCardData, CARD_CACHE_FILE_FORMAT **out)
|
|
|
|
|
{
|
|
|
|
|
struct md_file *file = NULL;
|
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
md_fs_find_file(pCardData, NULL, "cardcf", &file);
|
|
|
|
|
if (!file) {
|
|
|
|
|
logprintf(pCardData, 2, "file 'cardcf' not found\n");
|
|
|
|
|
return SCARD_E_FILE_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
if (!file->blob || file->size < MD_CARDCF_LENGTH)
|
|
|
|
|
return SCARD_E_INVALID_VALUE;
|
|
|
|
|
if (out)
|
|
|
|
|
*out = (CARD_CACHE_FILE_FORMAT *)file->blob;
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_set_cardapps(PCARD_DATA pCardData, struct md_file *file)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
unsigned char mscp[8] = {'m','s','c','p',0,0,0,0};
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !file)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_set_content(pCardData, file, mscp, sizeof(mscp));
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "mscp(%i)\n", file->size);
|
|
|
|
|
loghex(pCardData, 3, file->blob, file->size);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-09 06:19:51 +00:00
|
|
|
|
/* check if the card has root certificates. If yes, notify the base csp by creating the msroots file */
|
2015-04-18 19:43:13 +00:00
|
|
|
|
static DWORD
|
2017-03-09 06:19:51 +00:00
|
|
|
|
md_fs_add_msroots(PCARD_DATA pCardData, struct md_file **head)
|
2015-04-18 19:43:13 +00:00
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
int rv, ii, cert_num;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS];
|
|
|
|
|
if (!pCardData || !head)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC *) pCardData->pvVendorSpecific;
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_CERT_X509, prkey_objs, MD_MAX_KEY_CONTAINERS);
|
|
|
|
|
if (rv < 0) {
|
|
|
|
|
logprintf(pCardData, 0, "certificate enumeration failed: %s\n", sc_strerror(rv));
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
cert_num = rv;
|
|
|
|
|
for(ii = 0; ii < cert_num; ii++) {
|
|
|
|
|
struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) prkey_objs[ii]->data;
|
|
|
|
|
if (cert_info->authority) {
|
2017-03-09 06:19:51 +00:00
|
|
|
|
dwret = md_fs_add_file(pCardData, head, "msroots", EveryoneReadUserWriteAc, NULL, 0, NULL);
|
2015-04-18 19:43:13 +00:00
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/*
|
|
|
|
|
* Set the content of the 'soft' 'cmapfile':
|
|
|
|
|
* 1. Initialize internal p15_contaniers with the existing private keys PKCS#15 objects;
|
|
|
|
|
* 2. Try to read the content of the PKCS#15 'DATA' object 'CSP':'cmapfile',
|
2016-04-06 16:20:36 +00:00
|
|
|
|
* If some record from the 'DATA' object references an existing key:
|
2012-05-31 14:40:36 +00:00
|
|
|
|
* 2a. Update the non-pkcs#15 attributes of the corresponding internal p15_container;
|
|
|
|
|
* 2b. Change the index of internal p15_container according to the index from 'DATA' file.
|
2016-04-06 16:20:36 +00:00
|
|
|
|
* Records from 'DATA' file are ignored is they do not have
|
|
|
|
|
* the corresponding PKCS#15 private key object.
|
2012-05-31 14:40:36 +00:00
|
|
|
|
* 3. Initalize the content of the 'soft' 'cmapfile' from the inernal p15-containers.
|
|
|
|
|
*/
|
|
|
|
|
static DWORD
|
|
|
|
|
md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
PCONTAINER_MAP_RECORD p;
|
|
|
|
|
sc_pkcs15_pubkey_t *pubkey = NULL;
|
|
|
|
|
unsigned char *cmap_buf = NULL;
|
|
|
|
|
size_t cmap_len;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
int ii, rv, conts_num, found_default = 0;
|
|
|
|
|
/* struct sc_pkcs15_data *data_object; */
|
|
|
|
|
struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS];
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !file)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2015-10-11 16:51:36 +00:00
|
|
|
|
logprintf(pCardData, 2, "set 'cmapfile'\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
cmap_len = MD_MAX_KEY_CONTAINERS*sizeof(CONTAINER_MAP_RECORD);
|
|
|
|
|
cmap_buf = pCardData->pfnCspAlloc(cmap_len);
|
|
|
|
|
if(!cmap_buf)
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
memset(cmap_buf, 0, cmap_len);
|
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_PRKEY, prkey_objs, MD_MAX_KEY_CONTAINERS);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (rv < 0) {
|
|
|
|
|
logprintf(pCardData, 0, "Private key enumeration failed: %s\n", sc_strerror(rv));
|
|
|
|
|
return SCARD_F_UNKNOWN_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conts_num = rv;
|
|
|
|
|
logprintf(pCardData, 2, "Found %d private key(s) in the card.\n", conts_num);
|
|
|
|
|
|
|
|
|
|
/* Initialize the P15 container array with the existing keys */
|
|
|
|
|
for(ii = 0; ii < conts_num; ii++) {
|
|
|
|
|
struct sc_pkcs15_object *key_obj = prkey_objs[ii], *cert_obj = NULL;
|
|
|
|
|
struct sc_pkcs15_prkey_info *prkey_info = (struct sc_pkcs15_prkey_info *)key_obj->data;
|
|
|
|
|
struct md_pkcs15_container *cont = &vs->p15_containers[ii];
|
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if(key_obj->type != SC_PKCS15_TYPE_PRKEY_RSA && key_obj->type != SC_PKCS15_TYPE_PRKEY_EC) {
|
|
|
|
|
logprintf(pCardData, 7, "Non 'RSA' 'EC' key (type:%X) are ignored\n", key_obj->type);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 16:20:36 +00:00
|
|
|
|
dwret = md_contguid_build_cont_guid_from_key(pCardData, key_obj, cont->guid);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
2013-12-25 19:57:42 +00:00
|
|
|
|
|
2015-10-11 13:20:04 +00:00
|
|
|
|
/* replace the OpenSC guid by a Windows Guid if needed
|
|
|
|
|
Typically used in the certificate enrollment process.
|
|
|
|
|
Windows create a new container with a Windows guid, close the context, then create a new context and look for the previous container.
|
|
|
|
|
If we return our guid, it fails because the Windows guid can't be found.
|
|
|
|
|
The overwrite is present to avoid this conversion been replaced by md_pkcs15_update_container_from_do*/
|
2016-04-06 16:20:36 +00:00
|
|
|
|
// cont->guid_overwrite = md_contguid_find_conversion(pCardData, cont->guid);
|
2015-10-11 13:20:04 +00:00
|
|
|
|
|
2016-04-06 16:20:36 +00:00
|
|
|
|
// cont->flags = CONTAINER_MAP_VALID_CONTAINER;
|
|
|
|
|
dwret = md_cont_flags_from_key(pCardData, key_obj, &cont->flags);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
if (cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER)
|
|
|
|
|
found_default = 1;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* AT_KEYEXCHANGE is more general key usage,
|
2016-04-06 16:20:36 +00:00
|
|
|
|
* it allows 'decryption' as well as 'signature' key usage.
|
|
|
|
|
* AT_SIGNATURE allows only 'signature' usage.
|
|
|
|
|
*/
|
2015-10-11 13:20:04 +00:00
|
|
|
|
cont->size_key_exchange = cont->size_sign = 0;
|
|
|
|
|
if (key_obj->type == SC_PKCS15_TYPE_PRKEY_RSA) {
|
|
|
|
|
if (prkey_info->usage & USAGE_ANY_DECIPHER)
|
|
|
|
|
cont->size_key_exchange = prkey_info->modulus_length;
|
|
|
|
|
else if (prkey_info->usage & USAGE_ANY_SIGN)
|
|
|
|
|
cont->size_sign = prkey_info->modulus_length;
|
|
|
|
|
else
|
|
|
|
|
cont->size_key_exchange = prkey_info->modulus_length;
|
|
|
|
|
} else if (key_obj->type == SC_PKCS15_TYPE_PRKEY_EC) {
|
|
|
|
|
if (prkey_info->usage & USAGE_ANY_AGREEMENT)
|
|
|
|
|
cont->size_key_exchange = prkey_info->field_length;
|
|
|
|
|
else if (prkey_info->usage & USAGE_ANY_SIGN)
|
|
|
|
|
cont->size_sign = prkey_info->field_length;
|
|
|
|
|
else
|
|
|
|
|
cont->size_key_exchange = prkey_info->field_length;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-06 06:21:20 +00:00
|
|
|
|
logprintf(pCardData, 7, "Container[%i]'s guid=%.*s\n", ii, (int) sizeof cont->guid, cont->guid);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 7, "Container[%i]'s key-exchange:%i, sign:%i\n", ii, cont->size_key_exchange, cont->size_sign);
|
|
|
|
|
|
|
|
|
|
cont->id = prkey_info->id;
|
|
|
|
|
cont->prkey_obj = prkey_objs[ii];
|
|
|
|
|
|
|
|
|
|
/* Try to find the friend objects: certficate and public key */
|
|
|
|
|
if (!sc_pkcs15_find_cert_by_id(vs->p15card, &cont->id, &cont->cert_obj))
|
2015-10-04 15:33:14 +00:00
|
|
|
|
logprintf(pCardData, 2, "found certificate friend '%.*s'\n", (int) sizeof cont->cert_obj->label, cont->cert_obj->label);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
if (!sc_pkcs15_find_pubkey_by_id(vs->p15card, &cont->id, &cont->pubkey_obj))
|
2015-10-04 15:33:14 +00:00
|
|
|
|
logprintf(pCardData, 2, "found public key friend '%.*s'\n", (int) sizeof cont->pubkey_obj->label, cont->pubkey_obj->label);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (conts_num) {
|
2013-12-25 19:57:42 +00:00
|
|
|
|
/* Read 'CMAPFILE' (Gemalto style) and update the attributes of P15 containers */
|
2016-04-06 16:20:36 +00:00
|
|
|
|
#if 0
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct sc_pkcs15_object *dobjs[MD_MAX_KEY_CONTAINERS + 1], *default_cont = NULL;
|
|
|
|
|
int num_dobjs = MD_MAX_KEY_CONTAINERS + 1;
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_DATA_OBJECT, dobjs, num_dobjs);
|
|
|
|
|
if (rv < 0) {
|
|
|
|
|
logprintf(pCardData, 0, "'DATA' object enumeration failed: %s\n", sc_strerror(rv));
|
|
|
|
|
return SCARD_F_UNKNOWN_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
num_dobjs = rv;
|
|
|
|
|
logprintf(pCardData, 2, "Found %d 'DATA' objects.\n", num_dobjs);
|
|
|
|
|
|
|
|
|
|
for (ii=0;ii<num_dobjs;ii++) {
|
|
|
|
|
struct sc_pkcs15_data_info *dinfo = (struct sc_pkcs15_data_info *)dobjs[ii]->data;
|
|
|
|
|
|
|
|
|
|
if (strcmp(dinfo->app_label, MD_DATA_APPLICAITON_NAME))
|
|
|
|
|
continue;
|
|
|
|
|
|
2015-10-04 15:33:14 +00:00
|
|
|
|
logprintf(pCardData, 2, "Found 'DATA' object '%.*s'\n", (int) sizeof dobjs[ii]->label, dobjs[ii]->label);
|
|
|
|
|
if (!strncmp(dobjs[ii]->label, MD_DATA_DEFAULT_CONT_LABEL, sizeof dobjs[ii]->label)) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
default_cont = dobjs[ii];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwret = md_pkcs15_update_container_from_do(pCardData, dobjs[ii]);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "Cannot update container from DO: %li", dwret);
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (default_cont) {
|
|
|
|
|
dwret = md_pkcs15_default_container_from_do(pCardData, default_cont);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "Cannot set default container from DO: %li", dwret);
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-06 16:20:36 +00:00
|
|
|
|
#endif
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/* Initialize 'CMAPFILE' content from the P15 containers */
|
|
|
|
|
p = (PCONTAINER_MAP_RECORD)cmap_buf;
|
|
|
|
|
for (ii=0; ii<MD_MAX_KEY_CONTAINERS; ii++) {
|
|
|
|
|
struct sc_pkcs15_object *cert_obj = NULL;
|
|
|
|
|
|
|
|
|
|
if (!(vs->p15_containers[ii].flags & CONTAINER_MAP_VALID_CONTAINER))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!found_default) {
|
|
|
|
|
vs->p15_containers[ii].flags |= CONTAINER_MAP_DEFAULT_CONTAINER;
|
|
|
|
|
found_default = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mbstowcs((p+ii)->wszGuid, vs->p15_containers[ii].guid, MAX_CONTAINER_NAME_LEN + 1);
|
|
|
|
|
(p+ii)->bFlags = vs->p15_containers[ii].flags;
|
2015-04-25 21:29:03 +00:00
|
|
|
|
(p+ii)->wSigKeySizeBits = (WORD) vs->p15_containers[ii].size_sign;
|
|
|
|
|
(p+ii)->wKeyExchangeKeySizeBits = (WORD) vs->p15_containers[ii].size_key_exchange;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
if (vs->p15_containers[ii].cert_obj) {
|
|
|
|
|
char k_name[6];
|
|
|
|
|
|
|
|
|
|
if (vs->p15_containers[ii].size_key_exchange) {
|
2015-10-10 20:07:49 +00:00
|
|
|
|
_snprintf_s((char *)k_name, sizeof(k_name), sizeof(k_name)-1, "kxc%02i", ii);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = md_fs_add_file(pCardData, &(file->next), k_name, file->acl, NULL, 0, NULL);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (vs->p15_containers[ii].size_sign) {
|
2015-10-10 20:07:49 +00:00
|
|
|
|
_snprintf_s((char *)k_name, sizeof(k_name), sizeof(k_name)-1, "ksc%02i", ii);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = md_fs_add_file(pCardData, &(file->next), k_name, file->acl, NULL, 0, NULL);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 7, "cmapfile entry(%d) '%s' ",ii, vs->p15_containers[ii].guid);
|
|
|
|
|
loghex(pCardData, 7, (PBYTE) (p+ii), sizeof(CONTAINER_MAP_RECORD));
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
2017-03-09 06:19:51 +00:00
|
|
|
|
dwret = md_fs_add_msroots(pCardData, &(file->next));
|
2015-04-18 19:43:13 +00:00
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
dwret = md_fs_set_content(pCardData, file, cmap_buf, cmap_len);
|
|
|
|
|
pCardData->pfnCspFree(cmap_buf);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "cmap(%i)\n", file->size);
|
|
|
|
|
loghex(pCardData, 3, file->blob, file->size);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialize internal 'soft' file system
|
|
|
|
|
*/
|
|
|
|
|
static DWORD
|
|
|
|
|
md_fs_init(PCARD_DATA pCardData)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
struct md_file *cardid, *cardcf, *cardapps, *cmapfile;
|
|
|
|
|
struct md_directory *mscp;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !pCardData->pvVendorSpecific)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = pCardData->pvVendorSpecific;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_add_file(pCardData, &(vs->root.files), "cardid", EveryoneReadAdminWriteAc, NULL, 0, &cardid);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
dwret = md_set_cardid(pCardData, cardid);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_add_file(pCardData, &(vs->root.files), "cardcf", EveryoneReadUserWriteAc, NULL, 0, &cardcf);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
dwret = md_set_cardcf(pCardData, cardcf);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_add_file(pCardData, &(vs->root.files), "cardapps", EveryoneReadAdminWriteAc, NULL, 0, &cardapps);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
dwret = md_set_cardapps(pCardData, cardapps);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_add_directory(pCardData, &(vs->root.subdirs), "mscp", UserCreateDeleteDirAc, &mscp);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_add_file(pCardData, &(mscp->files), "cmapfile", EveryoneReadUserWriteAc, NULL, 0, &cmapfile);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
dwret = md_set_cmapfile(pCardData, cmapfile);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
|
2015-03-28 12:04:41 +00:00
|
|
|
|
#ifdef OPENSSL_VERSION_NUMBER
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 3, "MD virtual file system initialized; OPENSSL_VERSION_NUMBER 0x%Xl\n", OPENSSL_VERSION_NUMBER);
|
2015-03-28 12:04:41 +00:00
|
|
|
|
#else
|
|
|
|
|
logprintf(pCardData, 3, "MD virtual file system initialized; Without OPENSSL\n");
|
|
|
|
|
#endif
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create SC context */
|
|
|
|
|
static DWORD
|
|
|
|
|
md_create_context(PCARD_DATA pCardData, VENDOR_SPECIFIC *vs)
|
|
|
|
|
{
|
|
|
|
|
sc_context_param_t ctx_param;
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "create sc ccontext\n");
|
|
|
|
|
vs->ctx = NULL;
|
|
|
|
|
|
|
|
|
|
memset(&ctx_param, 0, sizeof(ctx_param));
|
|
|
|
|
ctx_param.ver = 1;
|
|
|
|
|
ctx_param.app_name = "cardmod";
|
|
|
|
|
|
|
|
|
|
r = sc_context_create(&(vs->ctx), &ctx_param);
|
|
|
|
|
if (r) {
|
|
|
|
|
logprintf(pCardData, 0, "Failed to establish context: %s\n", sc_strerror(r));
|
|
|
|
|
return SCARD_F_UNKNOWN_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "sc context created\n");
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DWORD
|
2015-04-17 19:39:41 +00:00
|
|
|
|
md_card_capabilities(PCARD_DATA pCardData, PCARD_CAPABILITIES pCardCapabilities)
|
2012-05-31 14:40:36 +00:00
|
|
|
|
{
|
|
|
|
|
if (!pCardCapabilities)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
if (pCardCapabilities->dwVersion != CARD_CAPABILITIES_CURRENT_VERSION && pCardCapabilities->dwVersion != 0)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
|
|
|
|
|
pCardCapabilities->dwVersion = CARD_CAPABILITIES_CURRENT_VERSION;
|
|
|
|
|
pCardCapabilities->fCertificateCompression = TRUE;
|
2015-04-17 16:04:05 +00:00
|
|
|
|
/* a read only card cannot generate new keys */
|
|
|
|
|
pCardCapabilities->fKeyGen = ! md_is_read_only(pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_free_space(PCARD_DATA pCardData, PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
int count, idx;
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !pCardFreeSpaceInfo)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
if (pCardFreeSpaceInfo->dwVersion > CARD_FREE_SPACE_INFO_CURRENT_VERSION )
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
/* Count free containers */
|
|
|
|
|
for (idx=0, count=0; idx<MD_MAX_KEY_CONTAINERS; idx++)
|
|
|
|
|
if (!vs->p15_containers[idx].prkey_obj)
|
|
|
|
|
count++;
|
|
|
|
|
|
|
|
|
|
pCardFreeSpaceInfo->dwVersion = CARD_FREE_SPACE_INFO_CURRENT_VERSION;
|
|
|
|
|
pCardFreeSpaceInfo->dwBytesAvailable = CARD_DATA_VALUE_UNKNOWN;
|
|
|
|
|
pCardFreeSpaceInfo->dwKeyContainersAvailable = count;
|
|
|
|
|
pCardFreeSpaceInfo->dwMaxKeyContainers = MD_MAX_KEY_CONTAINERS;
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check the new key to be created for the compatibility with card:
|
|
|
|
|
* - for the key to be generated the card needs to support the mechanism and size;
|
|
|
|
|
* - for the key to be imported checked also the validity of supplied key blob.
|
|
|
|
|
*/
|
|
|
|
|
static DWORD
|
|
|
|
|
md_check_key_compatibility(PCARD_DATA pCardData, DWORD flags, DWORD key_type,
|
|
|
|
|
DWORD key_size, BYTE *pbKeyData)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct sc_algorithm_info *algo_info;
|
|
|
|
|
unsigned int count, key_algo;
|
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
switch(key_type) {
|
|
|
|
|
case AT_SIGNATURE:
|
|
|
|
|
case AT_KEYEXCHANGE:
|
|
|
|
|
key_algo = SC_ALGORITHM_RSA;
|
|
|
|
|
break;
|
|
|
|
|
case AT_ECDHE_P256 :
|
|
|
|
|
case AT_ECDHE_P384 :
|
|
|
|
|
case AT_ECDHE_P521 :
|
|
|
|
|
case AT_ECDSA_P256 :
|
|
|
|
|
case AT_ECDSA_P384 :
|
|
|
|
|
case AT_ECDSA_P521 :
|
|
|
|
|
key_algo = SC_ALGORITHM_EC;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
logprintf(pCardData, 3, "Unsupported key type: 0x%X\n", key_type);
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
if (flags & CARD_CREATE_CONTAINER_KEY_IMPORT) {
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if (key_algo == SC_ALGORITHM_RSA) {
|
|
|
|
|
PUBLICKEYSTRUC *pub_struc = (PUBLICKEYSTRUC *)pbKeyData;
|
|
|
|
|
RSAPUBKEY *pub_rsa = (RSAPUBKEY *)(pbKeyData + sizeof(PUBLICKEYSTRUC));
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if (!pub_struc) {
|
|
|
|
|
logprintf(pCardData, 3, "No data for the key import operation\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
else if (pub_struc->bType != PRIVATEKEYBLOB) {
|
|
|
|
|
logprintf(pCardData, 3, "Invalid blob data for the key import operation\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
else if ((key_type == AT_KEYEXCHANGE) && (pub_struc->aiKeyAlg != CALG_RSA_KEYX)) {
|
|
|
|
|
logprintf(pCardData, 3, "Expected KEYEXCHANGE type of blob\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
else if ((key_type == AT_SIGNATURE) && (pub_struc->aiKeyAlg != CALG_RSA_SIGN)) {
|
|
|
|
|
logprintf(pCardData, 3, "Expected KEYSIGN type of blob\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-10-14 20:48:41 +00:00
|
|
|
|
if (pub_rsa->magic == BCRYPT_RSAPUBLIC_MAGIC || pub_rsa->magic == BCRYPT_RSAPRIVATE_MAGIC) {
|
2015-09-25 20:22:29 +00:00
|
|
|
|
key_size = pub_rsa->bitlen;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 3, "'Magic' control failed\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
logprintf(pCardData, 3, "Set key size to %i\n", key_size);
|
|
|
|
|
} else if (key_algo == SC_ALGORITHM_EC) {
|
|
|
|
|
BCRYPT_ECCKEY_BLOB *pub_ecc = (BCRYPT_ECCKEY_BLOB *)pbKeyData;
|
|
|
|
|
switch(key_type) {
|
|
|
|
|
case AT_ECDSA_P256:
|
|
|
|
|
if (pub_ecc->dwMagic != BCRYPT_ECDSA_PRIVATE_P256_MAGIC) {
|
|
|
|
|
logprintf(pCardData, 3, "Expected AT_ECDSA_P256 magic\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
key_size = 256;
|
|
|
|
|
break;
|
|
|
|
|
case AT_ECDSA_P384:
|
|
|
|
|
if (pub_ecc->dwMagic != BCRYPT_ECDSA_PRIVATE_P384_MAGIC) {
|
|
|
|
|
logprintf(pCardData, 3, "Expected AT_ECDSA_P384 magic\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
key_size = 384;
|
|
|
|
|
break;
|
|
|
|
|
case AT_ECDSA_P521:
|
|
|
|
|
if (pub_ecc->dwMagic != BCRYPT_ECDSA_PRIVATE_P521_MAGIC) {
|
|
|
|
|
logprintf(pCardData, 3, "Expected AT_ECDSA_P521 magic\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
key_size = 521;
|
|
|
|
|
break;
|
|
|
|
|
case AT_ECDHE_P256:
|
|
|
|
|
if (pub_ecc->dwMagic != BCRYPT_ECDH_PRIVATE_P256_MAGIC) {
|
|
|
|
|
logprintf(pCardData, 3, "Expected AT_ECDHE_P256 magic\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
key_size = 256;
|
|
|
|
|
break;
|
|
|
|
|
case AT_ECDHE_P384:
|
|
|
|
|
if (pub_ecc->dwMagic != BCRYPT_ECDH_PRIVATE_P384_MAGIC) {
|
|
|
|
|
logprintf(pCardData, 3, "Expected AT_ECDHE_P384 magic\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
key_size = 384;
|
|
|
|
|
break;
|
|
|
|
|
case AT_ECDHE_P521:
|
|
|
|
|
if (pub_ecc->dwMagic != BCRYPT_ECDH_PRIVATE_P521_MAGIC) {
|
|
|
|
|
logprintf(pCardData, 3, "Expected AT_ECDHE_P521 magic\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
key_size = 521;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 3, "Set key size to %i\n", key_size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
count = vs->p15card->card->algorithm_count;
|
|
|
|
|
for (algo_info = vs->p15card->card->algorithms; count--; algo_info++) {
|
|
|
|
|
if (algo_info->algorithm != key_algo || algo_info->key_length != key_size)
|
|
|
|
|
continue;
|
|
|
|
|
logprintf(pCardData, 3, "Key compatible with the card capabilities\n");
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "No card support for key(type:0x%X,size:0x%X)\n", key_type, key_size);
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_pkcs15_generate_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, DWORD key_size)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct sc_card *card = NULL;
|
|
|
|
|
struct sc_profile *profile = NULL;
|
|
|
|
|
struct sc_pkcs15_object *pin_obj = NULL;
|
|
|
|
|
struct sc_pkcs15_auth_info *auth_info = NULL;
|
|
|
|
|
struct sc_app_info *app_info = NULL;
|
|
|
|
|
struct sc_pkcs15init_keygen_args keygen_args;
|
|
|
|
|
struct sc_pkcs15init_pubkeyargs pub_args;
|
|
|
|
|
struct md_pkcs15_container *cont = NULL;
|
|
|
|
|
int rv;
|
|
|
|
|
DWORD dw, dwret = SCARD_F_INTERNAL_ERROR;
|
2015-10-10 13:39:27 +00:00
|
|
|
|
CHAR szGuid[MAX_CONTAINER_NAME_LEN +1] = "Default key label";
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
card = vs->p15card->card;
|
|
|
|
|
|
|
|
|
|
memset(&pub_args, 0, sizeof(pub_args));
|
|
|
|
|
memset(&keygen_args, 0, sizeof(keygen_args));
|
2015-10-10 13:39:27 +00:00
|
|
|
|
keygen_args.prkey_args.label = szGuid;
|
|
|
|
|
keygen_args.pubkey_label = szGuid;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
if (key_type == AT_SIGNATURE) {
|
|
|
|
|
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA;
|
|
|
|
|
pub_args.key.algorithm = SC_ALGORITHM_RSA;
|
|
|
|
|
keygen_args.prkey_args.x509_usage = MD_KEY_USAGE_SIGNATURE;
|
|
|
|
|
}
|
|
|
|
|
else if (key_type == AT_KEYEXCHANGE) {
|
|
|
|
|
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA;
|
|
|
|
|
pub_args.key.algorithm = SC_ALGORITHM_RSA;
|
|
|
|
|
keygen_args.prkey_args.x509_usage = MD_KEY_USAGE_KEYEXCHANGE;
|
|
|
|
|
}
|
2015-09-25 20:22:29 +00:00
|
|
|
|
else if ((key_type == AT_ECDSA_P256) || (key_type == AT_ECDSA_P384) || (key_type == AT_ECDSA_P521)) {
|
|
|
|
|
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EC;
|
|
|
|
|
pub_args.key.algorithm = SC_ALGORITHM_EC;
|
|
|
|
|
keygen_args.prkey_args.x509_usage = MD_KEY_USAGE_SIGNATURE;
|
|
|
|
|
}
|
|
|
|
|
else if ((key_type == AT_ECDHE_P256) || (key_type == AT_ECDHE_P384) || (key_type == AT_ECDHE_P521)) {
|
|
|
|
|
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EC;
|
|
|
|
|
pub_args.key.algorithm = SC_ALGORITHM_EC;
|
|
|
|
|
keygen_args.prkey_args.x509_usage = MD_KEY_USAGE_KEYEXCHANGE_ECC;
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 3, "MdGenerateKey(): unsupported key type: 0x%X\n", key_type);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
if (pub_args.key.algorithm == SC_ALGORITHM_EC) {
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.field_length = key_size;
|
|
|
|
|
if ((key_type == AT_ECDSA_P256)|| (key_type == AT_ECDHE_P256)) {
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.named_curve = "secp256r1";
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.der.len = 10;
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.der.value = "\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x07";
|
|
|
|
|
} else if ((key_type == AT_ECDSA_P384)|| (key_type == AT_ECDHE_P384)) {
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.named_curve = "secp384r1";
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.der.len = 7;
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.der.value = "\x06\x05\x2B\x81\x04\x00\x22";
|
|
|
|
|
} else if ((key_type == AT_ECDSA_P521)|| (key_type == AT_ECDHE_P521)) {
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.named_curve = "secp521r1";
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.der.len = 7;
|
|
|
|
|
keygen_args.prkey_args.key.u.ec.params.der.value = "\x06\x05\x2B\x81\x04\x00\x23";
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
keygen_args.prkey_args.access_flags = MD_KEY_ACCESS;
|
|
|
|
|
|
|
|
|
|
dw = md_get_pin_by_role(pCardData, ROLE_USER, &pin_obj);
|
|
|
|
|
if (dw != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "MdGenerateKey(): cannot get User PIN object");
|
|
|
|
|
return dw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auth_info = (struct sc_pkcs15_auth_info *) pin_obj->data;
|
|
|
|
|
keygen_args.prkey_args.auth_id = pub_args.auth_id = auth_info->auth_id;
|
|
|
|
|
|
|
|
|
|
rv = sc_lock(card);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdGenerateKey(): cannot lock card\n");
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_info = vs->p15card->app;
|
2015-09-30 20:47:16 +00:00
|
|
|
|
rv = sc_pkcs15init_bind(card, "pkcs15", NULL, NULL, &profile);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdGenerateKey(): PKCS#15 bind failed\n");
|
|
|
|
|
sc_unlock(card);
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_finalize_profile(card, profile, app_info ? &app_info->aid : NULL);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdGenerateKey(): cannot finalize profile\n");
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sc_pkcs15init_set_p15card(profile, vs->p15card);
|
|
|
|
|
cont = &(vs->p15_containers[idx]);
|
2013-12-29 11:41:36 +00:00
|
|
|
|
|
2015-10-10 13:39:27 +00:00
|
|
|
|
/* use the Windows Guid as input to determine some characteristics of the key such as the label or the id */
|
|
|
|
|
md_contguid_build_key_args_from_cont_guid(pCardData, cont->guid, &(keygen_args.prkey_args));
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
2015-10-10 13:39:27 +00:00
|
|
|
|
if (keygen_args.prkey_args.label == NULL) {
|
|
|
|
|
md_generate_guid(szGuid);
|
|
|
|
|
keygen_args.prkey_args.label = szGuid;
|
2013-12-29 11:46:51 +00:00
|
|
|
|
}
|
2015-10-10 13:39:27 +00:00
|
|
|
|
keygen_args.pubkey_label = keygen_args.prkey_args.label;
|
2013-12-29 11:46:51 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
rv = sc_pkcs15init_generate_key(vs->p15card, profile, &keygen_args, key_size, &cont->prkey_obj);
|
|
|
|
|
if (rv < 0) {
|
|
|
|
|
logprintf(pCardData, 3, "MdGenerateKey(): key generation failed: sc-error %i\n", rv);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 16:20:36 +00:00
|
|
|
|
dwret = md_contguid_add_conversion(pCardData, cont->prkey_obj, cont->guid);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
cont->id = ((struct sc_pkcs15_prkey_info *)cont->prkey_obj->data)->id;
|
|
|
|
|
cont->index = idx;
|
|
|
|
|
cont->flags = CONTAINER_MAP_VALID_CONTAINER;
|
|
|
|
|
|
2015-10-06 06:21:20 +00:00
|
|
|
|
logprintf(pCardData, 3, "MdGenerateKey(): generated key(idx:%i,id:%s,guid:%.*s)\n",
|
|
|
|
|
idx, sc_pkcs15_print_id(&cont->id),(int) sizeof cont->guid, cont->guid);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
sc_pkcs15init_unbind(profile);
|
|
|
|
|
sc_unlock(card);
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_pkcs15_store_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, BYTE *blob, DWORD blob_size)
|
|
|
|
|
{
|
|
|
|
|
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct sc_card *card = NULL;
|
|
|
|
|
struct sc_profile *profile = NULL;
|
|
|
|
|
struct sc_pkcs15_object *pin_obj = NULL;
|
|
|
|
|
struct sc_app_info *app_info = NULL;
|
|
|
|
|
struct md_pkcs15_container *cont = NULL;
|
|
|
|
|
struct sc_pkcs15init_prkeyargs prkey_args;
|
|
|
|
|
struct sc_pkcs15init_pubkeyargs pubkey_args;
|
|
|
|
|
BYTE *ptr = blob;
|
|
|
|
|
EVP_PKEY *pkey=NULL;
|
|
|
|
|
int rv;
|
|
|
|
|
DWORD dw, dwret = SCARD_F_INTERNAL_ERROR;
|
2015-10-10 13:39:27 +00:00
|
|
|
|
CHAR szGuid[MAX_CONTAINER_NAME_LEN +1] = "Default key label";
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
card = vs->p15card->card;
|
|
|
|
|
|
|
|
|
|
pkey = b2i_PrivateKey(&ptr, blob_size);
|
|
|
|
|
if (!pkey) {
|
|
|
|
|
logprintf(pCardData, 1, "MdStoreKey() MSBLOB key parse error");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(&prkey_args, 0, sizeof(prkey_args));
|
|
|
|
|
rv = sc_pkcs15_convert_prkey(&prkey_args.key, pkey);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 1, "MdStoreKey() cannot convert private key");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(&pubkey_args, 0, sizeof(pubkey_args));
|
|
|
|
|
rv = sc_pkcs15_convert_pubkey(&pubkey_args.key, pkey);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 1, "MdStoreKey() cannot convert public key");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (key_type == AT_SIGNATURE) {
|
|
|
|
|
prkey_args.x509_usage = MD_KEY_USAGE_SIGNATURE;
|
|
|
|
|
pubkey_args.x509_usage = MD_KEY_USAGE_SIGNATURE;
|
|
|
|
|
}
|
|
|
|
|
else if (key_type == AT_KEYEXCHANGE) {
|
|
|
|
|
prkey_args.x509_usage = MD_KEY_USAGE_KEYEXCHANGE;
|
|
|
|
|
pubkey_args.x509_usage = MD_KEY_USAGE_KEYEXCHANGE;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreKey(): unsupported key type: 0x%X\n", key_type);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prkey_args.access_flags = MD_KEY_ACCESS;
|
|
|
|
|
|
|
|
|
|
dw = md_get_pin_by_role(pCardData, ROLE_USER, &pin_obj);
|
|
|
|
|
if (dw != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "MdStoreKey(): cannot get User PIN object");
|
|
|
|
|
return dw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prkey_args.auth_id = ((struct sc_pkcs15_auth_info *) pin_obj->data)->auth_id;
|
|
|
|
|
|
|
|
|
|
rv = sc_lock(card);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreKey(): cannot lock card\n");
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_info = vs->p15card->app;
|
2015-09-30 20:47:16 +00:00
|
|
|
|
rv = sc_pkcs15init_bind(card, "pkcs15", NULL, NULL, &profile);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreKey(): PKCS#15 bind failed\n");
|
|
|
|
|
sc_unlock(card);
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_finalize_profile(card, profile, app_info ? &app_info->aid : NULL);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreKey(): cannot finalize profile\n");
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sc_pkcs15init_set_p15card(profile, vs->p15card);
|
|
|
|
|
cont = &(vs->p15_containers[idx]);
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
2015-10-10 13:39:27 +00:00
|
|
|
|
prkey_args.label = szGuid;
|
|
|
|
|
/* use the Windows Guid as input to determine some characteristics of the key such as the label or the id */
|
|
|
|
|
md_contguid_build_key_args_from_cont_guid(pCardData, cont->guid, &prkey_args);
|
2016-04-06 16:20:36 +00:00
|
|
|
|
|
2015-10-10 13:39:27 +00:00
|
|
|
|
memcpy(pubkey_args.id.value, prkey_args.id.value, prkey_args.id.len);
|
|
|
|
|
pubkey_args.id.len = prkey_args.id.len;
|
|
|
|
|
pubkey_args.label = prkey_args.label;
|
2013-12-29 11:41:36 +00:00
|
|
|
|
|
2015-10-10 13:39:27 +00:00
|
|
|
|
if (prkey_args.label == szGuid) {
|
|
|
|
|
md_generate_guid(szGuid);
|
2013-12-29 11:46:51 +00:00
|
|
|
|
}
|
2015-10-10 13:39:27 +00:00
|
|
|
|
pubkey_args.label = prkey_args.label;
|
2013-12-29 11:46:51 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
rv = sc_pkcs15init_store_private_key(vs->p15card, profile, &prkey_args, &cont->prkey_obj);
|
|
|
|
|
if (rv < 0) {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreKey(): private key store failed: sc-error %i\n", rv);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_store_public_key(vs->p15card, profile, &pubkey_args, &cont->pubkey_obj);
|
|
|
|
|
if (rv < 0) {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreKey(): public key store failed: sc-error %i\n", rv);
|
|
|
|
|
goto done;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 16:20:36 +00:00
|
|
|
|
dwret = md_contguid_add_conversion(pCardData, cont->prkey_obj, cont->guid);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
2015-10-11 13:20:04 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
cont->id = ((struct sc_pkcs15_prkey_info *)cont->prkey_obj->data)->id;
|
|
|
|
|
cont->index = idx;
|
|
|
|
|
cont->flags |= CONTAINER_MAP_VALID_CONTAINER;
|
|
|
|
|
|
2015-10-06 06:21:20 +00:00
|
|
|
|
logprintf(pCardData, 3, "MdStoreKey(): stored key(idx:%i,id:%s,guid:%.*s)\n", idx, sc_pkcs15_print_id(&cont->id),(int) sizeof cont->guid,cont->guid);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
sc_pkcs15init_unbind(profile);
|
|
|
|
|
sc_unlock(card);
|
|
|
|
|
return dwret;
|
|
|
|
|
#else
|
|
|
|
|
logprintf(pCardData, 1, "MD store key not supported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
#endif
|
2011-03-23 18:37:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
md_pkcs15_store_certificate(PCARD_DATA pCardData, char *file_name, unsigned char *blob, size_t len)
|
2011-03-23 18:37:46 +00:00
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2013-12-29 11:41:36 +00:00
|
|
|
|
struct md_pkcs15_container *cont = NULL;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct sc_card *card = NULL;
|
|
|
|
|
struct sc_profile *profile = NULL;
|
|
|
|
|
struct sc_app_info *app_info = NULL;
|
|
|
|
|
struct sc_pkcs15_object *cert_obj;
|
|
|
|
|
struct sc_pkcs15init_certargs args;
|
2013-12-29 11:41:36 +00:00
|
|
|
|
int rv, idx;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
DWORD dwret = SCARD_F_INTERNAL_ERROR;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
2013-12-29 11:41:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "MdStoreCert(): store certificate '%s'\n", file_name);
|
2011-03-23 18:37:46 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
card = vs->p15card->card;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
|
args.der_encoded.value = blob;
|
|
|
|
|
args.der_encoded.len = len;
|
2015-05-10 09:48:45 +00:00
|
|
|
|
args.update = 1;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2013-12-29 11:41:36 +00:00
|
|
|
|
/* use container's ID as ID of certificate to store */
|
|
|
|
|
idx = -1;
|
2015-10-10 20:07:49 +00:00
|
|
|
|
if(sscanf_s(file_name, "ksc%d", &idx) > 0)
|
2013-12-29 11:41:36 +00:00
|
|
|
|
;
|
2015-10-10 20:07:49 +00:00
|
|
|
|
else if(sscanf_s(file_name, "kxc%d", &idx) > 0)
|
2013-12-29 11:41:36 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
if (idx >= 0 && idx < MD_MAX_KEY_CONTAINERS) {
|
|
|
|
|
cont = &(vs->p15_containers[idx]);
|
|
|
|
|
args.id = cont->id;
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreCert(): store certificate(idx:%i,id:%s)\n", idx, sc_pkcs15_print_id(&cont->id));
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
rv = sc_lock(card);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreCert(): cannot lock card\n");
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
app_info = vs->p15card->app;
|
2015-09-30 20:47:16 +00:00
|
|
|
|
rv = sc_pkcs15init_bind(card, "pkcs15", NULL, NULL, &profile);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreCert(): PKCS#15 bind failed\n");
|
|
|
|
|
sc_unlock(card);
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
rv = sc_pkcs15init_finalize_profile(card, profile, app_info ? &app_info->aid : NULL);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreCert(): cannot finalize profile\n");
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sc_pkcs15init_set_p15card(profile, vs->p15card);
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_store_certificate(vs->p15card, profile, &args, &cert_obj);
|
|
|
|
|
if (rv < 0) {
|
|
|
|
|
logprintf(pCardData, 3, "MdStoreCert(): cannot store certificate: sc-error %i\n", rv);
|
|
|
|
|
goto done;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
dwret = SCARD_S_SUCCESS;
|
|
|
|
|
done:
|
|
|
|
|
sc_pkcs15init_unbind(profile);
|
|
|
|
|
sc_unlock(card);
|
|
|
|
|
return dwret;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
static DWORD
|
2015-09-25 20:22:29 +00:00
|
|
|
|
md_query_key_sizes(PCARD_DATA pCardData, DWORD dwKeySpec, CARD_KEY_SIZES *pKeySizes)
|
2012-05-31 14:40:36 +00:00
|
|
|
|
{
|
2015-09-25 20:22:29 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
|
|
|
|
struct sc_algorithm_info* algo_info;
|
|
|
|
|
int count = 0, i, key_algo = 0, keysize = 0, flag;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pKeySizes)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
if (pKeySizes->dwVersion != CARD_KEY_SIZES_CURRENT_VERSION && pKeySizes->dwVersion != 0)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
logprintf(pCardData, 1, "md_query_key_sizes: store dwKeySpec '%u'\n", dwKeySpec);
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
count = vs->p15card->card->algorithm_count;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
pKeySizes->dwVersion = CARD_KEY_SIZES_CURRENT_VERSION;
|
|
|
|
|
pKeySizes->dwMinimumBitlen = 0;
|
|
|
|
|
pKeySizes->dwDefaultBitlen = 0;
|
|
|
|
|
pKeySizes->dwMaximumBitlen = 0;
|
|
|
|
|
pKeySizes->dwIncrementalBitlen = 0;
|
|
|
|
|
|
|
|
|
|
/* dwKeySpec=0 is a special value when the key size is queried without specifing the algorithm.
|
|
|
|
|
Used on old minidriver version. In this case, it is RSA */
|
|
|
|
|
if ((dwKeySpec == 0) || (dwKeySpec == AT_KEYEXCHANGE) || (dwKeySpec == AT_SIGNATURE)) {
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
|
algo_info = vs->p15card->card->algorithms + i;
|
|
|
|
|
if (algo_info->algorithm == SC_ALGORITHM_RSA) {
|
|
|
|
|
|
|
|
|
|
if (pKeySizes->dwMinimumBitlen == 0 || pKeySizes->dwMinimumBitlen > algo_info->key_length) {
|
|
|
|
|
pKeySizes->dwMinimumBitlen = algo_info->key_length;
|
|
|
|
|
}
|
|
|
|
|
if (pKeySizes->dwMaximumBitlen == 0 || pKeySizes->dwMaximumBitlen < algo_info->key_length) {
|
|
|
|
|
pKeySizes->dwMaximumBitlen = algo_info->key_length;
|
|
|
|
|
}
|
|
|
|
|
if (algo_info->key_length == 2048) {
|
|
|
|
|
pKeySizes->dwDefaultBitlen = algo_info->key_length;
|
|
|
|
|
}
|
|
|
|
|
if (algo_info->key_length == 1536) {
|
|
|
|
|
pKeySizes->dwIncrementalBitlen = 512;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pKeySizes->dwMinimumBitlen == 0) {
|
|
|
|
|
logprintf(pCardData, 0, "No RSA key found\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
if (pKeySizes->dwDefaultBitlen == 0) {
|
|
|
|
|
logprintf(pCardData, 3, "No 2048 key found\n");
|
|
|
|
|
pKeySizes->dwDefaultBitlen = pKeySizes->dwMaximumBitlen;
|
|
|
|
|
}
|
|
|
|
|
if (pKeySizes->dwIncrementalBitlen == 0) {
|
|
|
|
|
pKeySizes->dwIncrementalBitlen = 1024;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
keysize = 0;
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
|
algo_info = vs->p15card->card->algorithms + i;
|
|
|
|
|
if (algo_info->algorithm == SC_ALGORITHM_EC) {
|
|
|
|
|
flag = SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_EXT_EC_NAMEDCURVE;
|
|
|
|
|
/* ECDHE */
|
|
|
|
|
if ((dwKeySpec == AT_ECDHE_P256) && (algo_info->key_length == 256) && (algo_info->flags & flag)) {
|
|
|
|
|
keysize = 256;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((dwKeySpec == AT_ECDHE_P384) && (algo_info->key_length == 384) && (algo_info->flags & flag)) {
|
|
|
|
|
keysize = 384;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((dwKeySpec == AT_ECDHE_P521) && (algo_info->key_length == 521) && (algo_info->flags & flag)) {
|
|
|
|
|
keysize = 521;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* ECDSA */
|
|
|
|
|
flag = SC_ALGORITHM_ECDSA_HASH_NONE|
|
|
|
|
|
SC_ALGORITHM_ECDSA_HASH_SHA1|
|
|
|
|
|
SC_ALGORITHM_ECDSA_HASH_SHA224|
|
|
|
|
|
SC_ALGORITHM_ECDSA_HASH_SHA256|
|
|
|
|
|
SC_ALGORITHM_EXT_EC_NAMEDCURVE;
|
|
|
|
|
if ((dwKeySpec == AT_ECDSA_P256) && (algo_info->key_length == 256) && (algo_info->flags & flag)) {
|
|
|
|
|
keysize = 256;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((dwKeySpec == AT_ECDSA_P384) && (algo_info->key_length == 384) && (algo_info->flags & flag)) {
|
|
|
|
|
keysize = 384;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((dwKeySpec == AT_ECDSA_P521) && (algo_info->key_length == 521) && (algo_info->flags & flag)) {
|
|
|
|
|
keysize = 521;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (keysize) {
|
|
|
|
|
pKeySizes->dwMinimumBitlen = keysize;
|
|
|
|
|
pKeySizes->dwDefaultBitlen = keysize;
|
|
|
|
|
pKeySizes->dwMaximumBitlen = keysize;
|
|
|
|
|
pKeySizes->dwIncrementalBitlen = 1;
|
|
|
|
|
} else {
|
|
|
|
|
logprintf(pCardData, 0, "No ECC key found (keyspec=%u)\n", dwKeySpec);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "Key compatible with the card capabilities\n");
|
|
|
|
|
logprintf(pCardData, 3, " dwMinimumBitlen: %u\n", pKeySizes->dwMinimumBitlen);
|
|
|
|
|
logprintf(pCardData, 3, " dwDefaultBitlen: %u\n", pKeySizes->dwDefaultBitlen);
|
|
|
|
|
logprintf(pCardData, 3, " dwMaximumBitlen: %u\n", pKeySizes->dwMaximumBitlen);
|
|
|
|
|
logprintf(pCardData, 3, " dwIncrementalBitlen: %u\n", pKeySizes->dwIncrementalBitlen);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
2015-04-19 17:51:22 +00:00
|
|
|
|
static VOID CenterWindow(HWND hwndWindow, HWND hwndParent)
|
|
|
|
|
{
|
|
|
|
|
RECT rectWindow, rectParent;
|
|
|
|
|
int nWidth,nHeight, nScreenWidth, nScreenHeight;
|
|
|
|
|
int nX, nY;
|
|
|
|
|
GetWindowRect(hwndWindow, &rectWindow);
|
|
|
|
|
|
|
|
|
|
nWidth = rectWindow.right - rectWindow.left;
|
|
|
|
|
nHeight = rectWindow.bottom - rectWindow.top;
|
|
|
|
|
|
|
|
|
|
nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
|
|
|
|
|
nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
|
|
2015-10-16 07:58:01 +00:00
|
|
|
|
// make the window relative to its parent
|
|
|
|
|
if (hwndParent != NULL) {
|
|
|
|
|
GetWindowRect(hwndParent, &rectParent);
|
|
|
|
|
nX = ((rectParent.right - rectParent.left) - nWidth) / 2 + rectParent.left;
|
|
|
|
|
nY = ((rectParent.bottom - rectParent.top) - nHeight) / 2 + rectParent.top;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
nX = (nScreenWidth - nWidth) /2;
|
|
|
|
|
nY = (nScreenHeight - nHeight) /2;
|
|
|
|
|
}
|
2015-04-19 17:51:22 +00:00
|
|
|
|
// make sure that the dialog box never moves outside of the screen
|
|
|
|
|
if (nX < 0) nX = 0;
|
|
|
|
|
if (nY < 0) nY = 0;
|
|
|
|
|
if (nX + nWidth > nScreenWidth) nX = nScreenWidth - nWidth;
|
|
|
|
|
if (nY + nHeight > nScreenHeight) nY = nScreenHeight - nHeight;
|
2015-10-16 07:58:01 +00:00
|
|
|
|
|
|
|
|
|
MoveWindow(hwndWindow, nX, nY, nWidth, nHeight, TRUE);
|
2015-04-19 17:51:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD WINAPI
|
|
|
|
|
md_dialog_perform_pin_operation_thread(PVOID lpParameter)
|
|
|
|
|
{
|
|
|
|
|
/* unstack the parameters */
|
|
|
|
|
LONG_PTR* parameter = (LONG_PTR*) lpParameter;
|
2015-04-25 21:29:03 +00:00
|
|
|
|
int operation = (int) parameter[0];
|
2015-04-19 17:51:22 +00:00
|
|
|
|
struct sc_pkcs15_card *p15card = (struct sc_pkcs15_card *) parameter[1];
|
|
|
|
|
struct sc_pkcs15_object *pin_obj = (struct sc_pkcs15_object *) parameter[2];
|
|
|
|
|
const u8 *pin1 = (const u8 *) parameter[3];
|
|
|
|
|
size_t pin1len = parameter[4];
|
|
|
|
|
const u8 *pin2 = (const u8 *) parameter[5];
|
|
|
|
|
size_t pin2len = parameter[6];
|
|
|
|
|
int rv = 0;
|
|
|
|
|
switch (operation)
|
|
|
|
|
{
|
|
|
|
|
case SC_PIN_CMD_VERIFY:
|
|
|
|
|
rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin1, pin1len);
|
|
|
|
|
break;
|
|
|
|
|
case SC_PIN_CMD_CHANGE:
|
|
|
|
|
rv = sc_pkcs15_change_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len);
|
|
|
|
|
break;
|
|
|
|
|
case SC_PIN_CMD_UNBLOCK:
|
|
|
|
|
rv = sc_pkcs15_unblock_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
rv = (DWORD) ERROR_INVALID_PARAMETER;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (parameter[9] != 0) {
|
|
|
|
|
EndDialog((HWND) parameter[9], rv);
|
|
|
|
|
}
|
|
|
|
|
return (DWORD) rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static INT_PTR CALLBACK md_dialog_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
|
|
|
switch (message)
|
|
|
|
|
{
|
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
|
{
|
|
|
|
|
HICON hIcon = NULL;
|
|
|
|
|
PCARD_DATA pCardData = (PCARD_DATA) (((LONG_PTR*)lParam)[7]);
|
|
|
|
|
VENDOR_SPECIFIC* vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
|
|
|
|
|
/* store parameter like pCardData for further use if needed */
|
|
|
|
|
SetWindowLongPtr(hWnd, GWLP_USERDATA, lParam);
|
|
|
|
|
/* change the text shown on the screen */
|
|
|
|
|
if (vs->wszPinContext ) {
|
|
|
|
|
SetWindowTextW(GetDlgItem(hWnd, IDC_PINPAD_TEXT), vs->wszPinContext );
|
|
|
|
|
}
|
|
|
|
|
CenterWindow(hWnd, vs->hwndParent);
|
|
|
|
|
/* load the information icon */
|
|
|
|
|
hIcon = (HICON) LoadImage(0, IDI_INFORMATION, IMAGE_ICON, 0, 0, LR_SHARED);
|
|
|
|
|
SendMessage(GetDlgItem(hWnd, IDC_PINPAD_ICON),STM_SETIMAGE,IMAGE_ICON, (LPARAM) hIcon);
|
2015-05-02 21:44:05 +00:00
|
|
|
|
/* change the icon */
|
|
|
|
|
hIcon = LoadIcon(g_inst, MAKEINTRESOURCE(IDI_LOGO));
|
|
|
|
|
if (hIcon)
|
|
|
|
|
{
|
|
|
|
|
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
|
|
|
|
|
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
|
|
|
|
|
}
|
2015-04-19 17:51:22 +00:00
|
|
|
|
/* launch the function in another thread context store the thread handle */
|
|
|
|
|
((LONG_PTR*)lParam)[9] = (LONG_PTR) hWnd;
|
|
|
|
|
((LONG_PTR*)lParam)[8] = (LONG_PTR) CreateThread(NULL, 0, md_dialog_perform_pin_operation_thread, (PVOID) lParam, 0, NULL);
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
case WM_DESTROY:
|
|
|
|
|
{
|
|
|
|
|
/* clean resources used */
|
|
|
|
|
LPARAM param = GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
|
|
|
|
if (param) {
|
|
|
|
|
HANDLE hThread = (HANDLE)((LONG_PTR*)param)[8];
|
|
|
|
|
CloseHandle(hThread);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
md_dialog_perform_pin_operation(PCARD_DATA pCardData, int operation, struct sc_pkcs15_card *p15card,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
struct sc_pkcs15_object *pin_obj,
|
|
|
|
|
const u8 *pin1, size_t pin1len,
|
|
|
|
|
const u8 *pin2, size_t pin2len, BOOL displayUI)
|
2015-04-19 17:51:22 +00:00
|
|
|
|
{
|
|
|
|
|
LONG_PTR parameter[10];
|
|
|
|
|
INT_PTR result = 0;
|
|
|
|
|
HWND hWndDlg = 0;
|
|
|
|
|
int rv = 0;
|
|
|
|
|
VENDOR_SPECIFIC* pv = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
/* stack the parameters */
|
|
|
|
|
parameter[0] = (LONG_PTR)operation;
|
|
|
|
|
parameter[1] = (LONG_PTR)p15card;
|
|
|
|
|
parameter[2] = (LONG_PTR)pin_obj;
|
|
|
|
|
parameter[3] = (LONG_PTR)pin1;
|
|
|
|
|
parameter[4] = (LONG_PTR)pin1len;
|
|
|
|
|
parameter[5] = (LONG_PTR)pin2;
|
|
|
|
|
parameter[6] = (LONG_PTR)pin2len;
|
|
|
|
|
parameter[7] = (LONG_PTR)pCardData;
|
|
|
|
|
parameter[8] = 0; /* place holder for thread handle */
|
|
|
|
|
parameter[9] = 0; /* place holder for window handle */
|
|
|
|
|
/* launch the function to perform in the same thread context */
|
|
|
|
|
if (!displayUI) {
|
|
|
|
|
rv = md_dialog_perform_pin_operation_thread(parameter);
|
|
|
|
|
SecureZeroMemory(parameter, sizeof(parameter));
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
/* launch the UI in the same thread context than the parent and the function to perform in another thread context
|
|
|
|
|
this is the only way to display a modal dialog attached to a parent (hwndParent != 0) */
|
|
|
|
|
result = DialogBoxParam(g_inst, MAKEINTRESOURCE(IDD_PINPAD), pv->hwndParent, md_dialog_proc, (LPARAM) parameter);
|
|
|
|
|
SecureZeroMemory(parameter, sizeof(parameter));
|
2015-04-25 21:29:03 +00:00
|
|
|
|
return (int) result;
|
2015-04-19 17:51:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD md_translate_OpenSC_to_Windows_error(int OpenSCerror, DWORD dwDefaulCode)
|
|
|
|
|
{
|
|
|
|
|
switch(OpenSCerror)
|
|
|
|
|
{
|
|
|
|
|
/* Errors related to reader operation */
|
|
|
|
|
case SC_ERROR_READER:
|
|
|
|
|
return SCARD_E_PROTO_MISMATCH;
|
|
|
|
|
case SC_ERROR_NO_READERS_FOUND:
|
|
|
|
|
return SCARD_E_NO_READERS_AVAILABLE;
|
|
|
|
|
case SC_ERROR_CARD_NOT_PRESENT:
|
|
|
|
|
return SCARD_E_NO_SMARTCARD;
|
|
|
|
|
case SC_ERROR_TRANSMIT_FAILED:
|
|
|
|
|
return SCARD_E_NOT_TRANSACTED;
|
|
|
|
|
case SC_ERROR_CARD_REMOVED:
|
|
|
|
|
return SCARD_W_REMOVED_CARD;
|
|
|
|
|
case SC_ERROR_CARD_RESET:
|
|
|
|
|
return SCARD_W_RESET_CARD;
|
|
|
|
|
case SC_ERROR_KEYPAD_CANCELLED:
|
|
|
|
|
return SCARD_W_CANCELLED_BY_USER;
|
|
|
|
|
case SC_ERROR_KEYPAD_MSG_TOO_LONG:
|
|
|
|
|
return SCARD_W_CARD_NOT_AUTHENTICATED;
|
|
|
|
|
case SC_ERROR_KEYPAD_PIN_MISMATCH:
|
|
|
|
|
return SCARD_E_INVALID_CHV;
|
|
|
|
|
case SC_ERROR_KEYPAD_TIMEOUT:
|
|
|
|
|
return ERROR_TIMEOUT;
|
|
|
|
|
case SC_ERROR_EVENT_TIMEOUT:
|
|
|
|
|
return SCARD_E_TIMEOUT;
|
|
|
|
|
case SC_ERROR_CARD_UNRESPONSIVE:
|
|
|
|
|
return SCARD_W_UNRESPONSIVE_CARD;
|
|
|
|
|
case SC_ERROR_READER_LOCKED:
|
|
|
|
|
return SCARD_E_SHARING_VIOLATION;
|
|
|
|
|
|
|
|
|
|
/* Resulting from a card command or related to the card*/
|
|
|
|
|
case SC_ERROR_INCORRECT_PARAMETERS:
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
case SC_ERROR_MEMORY_FAILURE:
|
|
|
|
|
case SC_ERROR_NOT_ENOUGH_MEMORY:
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
case SC_ERROR_NOT_ALLOWED:
|
|
|
|
|
return SCARD_W_SECURITY_VIOLATION;
|
|
|
|
|
case SC_ERROR_AUTH_METHOD_BLOCKED:
|
|
|
|
|
return SCARD_W_CHV_BLOCKED;
|
|
|
|
|
case SC_ERROR_PIN_CODE_INCORRECT:
|
|
|
|
|
return SCARD_W_WRONG_CHV;
|
|
|
|
|
|
|
|
|
|
/* Returned by OpenSC library when called with invalid arguments */
|
2015-04-20 21:25:57 +00:00
|
|
|
|
case SC_ERROR_INVALID_ARGUMENTS:
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
2015-04-19 17:51:22 +00:00
|
|
|
|
case SC_ERROR_BUFFER_TOO_SMALL:
|
|
|
|
|
return NTE_BUFFER_TOO_SMALL;
|
|
|
|
|
|
|
|
|
|
/* Resulting from OpenSC internal operation */
|
|
|
|
|
case SC_ERROR_INTERNAL:
|
|
|
|
|
return ERROR_INTERNAL_ERROR;
|
|
|
|
|
case SC_ERROR_NOT_SUPPORTED:
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
case SC_ERROR_NOT_IMPLEMENTED:
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return dwDefaulCode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (md_static_data.attach_check != MD_STATIC_PROCESS_ATTACHED)
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p hScard=0x%08X hSCardCtx=0x%08X CardDeleteContext\n",
|
|
|
|
|
GetCurrentProcessId(), GetCurrentThreadId(), pCardData, pCardData->hScard, pCardData->hSCardCtx);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
if(!vs)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
disassociate_card(pCardData);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(vs->ctx) {
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 6, "release context\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
sc_release_context(vs->ctx);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
md_static_data.flags |= MD_STATIC_FLAG_CONTEXT_DELETED;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
vs->ctx = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "**********************************************************************\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-04-12 11:34:18 +00:00
|
|
|
|
md_fs_finalize(pCardData);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
pCardData->pfnCspFree(pCardData->pvVendorSpecific);
|
|
|
|
|
pCardData->pvVendorSpecific = NULL;
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-12 07:40:12 +00:00
|
|
|
|
DWORD WINAPI CardQueryCapabilities(__in PCARD_DATA pCardData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__inout PCARD_CAPABILITIES pCardCapabilities)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
DWORD dwret;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2015-04-17 19:39:41 +00:00
|
|
|
|
logprintf(pCardData, 1, "pCardCapabilities=%p\n", pCardCapabilities);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData || !pCardCapabilities)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-04-17 16:04:05 +00:00
|
|
|
|
dwret = md_card_capabilities(pCardData, pCardCapabilities);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
check_reader_status(pCardData);
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardDeleteContainer(__in PCARD_DATA pCardData,
|
|
|
|
|
__in BYTE bContainerIndex,
|
|
|
|
|
__in DWORD dwReserved)
|
|
|
|
|
{
|
2015-09-30 20:52:37 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
struct md_pkcs15_container* cont;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardDeleteContainer(idx:%i)\n", bContainerIndex);
|
|
|
|
|
|
2015-09-30 20:52:37 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
if (bContainerIndex >= MD_MAX_KEY_CONTAINERS)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
if (!md_is_supports_container_key_gen(pCardData)) {
|
|
|
|
|
logprintf(pCardData, 1, "Denied 'deletion' mechanism to delete container.\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
if(!vs)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
cont = &(vs->p15_containers[bContainerIndex]);
|
|
|
|
|
|
|
|
|
|
dwret = md_pkcs15_delete_object(pCardData, cont->prkey_obj);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 1, "private key deletion failed\n");
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwret = md_pkcs15_delete_object(pCardData, cont->pubkey_obj);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 1, "public key deletion failed\n");
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ZeroMemory(cont, sizeof(struct md_pkcs15_container));
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 1, "key deleted\n");
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardCreateContainer(__in PCARD_DATA pCardData,
|
|
|
|
|
__in BYTE bContainerIndex,
|
|
|
|
|
__in DWORD dwFlags,
|
|
|
|
|
__in DWORD dwKeySpec,
|
|
|
|
|
__in DWORD dwKeySize,
|
|
|
|
|
__in PBYTE pbKeyData)
|
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardCreateContainer(idx:%i,flags:%X,type:%X,size:%i,data:%p)\n",
|
|
|
|
|
bContainerIndex, dwFlags, dwKeySpec, dwKeySize, pbKeyData);
|
|
|
|
|
|
|
|
|
|
if (pbKeyData) {
|
|
|
|
|
logprintf(pCardData, 7, "Key data\n");
|
|
|
|
|
loghex(pCardData, 7, pbKeyData, dwKeySize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwret = md_check_key_compatibility(pCardData, dwFlags, dwKeySpec, dwKeySize, pbKeyData);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "check key compatibility failed\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-29 11:53:41 +00:00
|
|
|
|
if (!md_is_supports_container_key_gen(pCardData)) {
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "Denied 'generate key' mechanism to create container.\n");
|
2013-12-29 11:53:41 +00:00
|
|
|
|
dwFlags &= ~CARD_CREATE_CONTAINER_KEY_GEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!md_is_supports_container_key_import(pCardData)) {
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "Denied 'import key' mechanism to create container.\n");
|
2013-12-29 11:53:41 +00:00
|
|
|
|
dwFlags &= ~CARD_CREATE_CONTAINER_KEY_IMPORT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!dwFlags) {
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "Unsupported create container mechanism.\n");
|
2013-12-29 11:53:41 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (dwFlags & CARD_CREATE_CONTAINER_KEY_GEN) {
|
|
|
|
|
dwret = md_pkcs15_generate_key(pCardData, bContainerIndex, dwKeySpec, dwKeySize);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "key generation failed\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return dwret;
|
|
|
|
|
}
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "key generated\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
else if ((dwFlags & CARD_CREATE_CONTAINER_KEY_IMPORT) && (pbKeyData != NULL)) {
|
|
|
|
|
dwret = md_pkcs15_store_key(pCardData, bContainerIndex, dwKeySpec, pbKeyData, dwKeySize);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "key store failed\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return dwret;
|
|
|
|
|
}
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "key imported\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
2013-12-29 11:54:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "Invalid dwFlags value: 0x%X\n", dwFlags);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
PUBLICKEYSTRUC publickeystruc;
|
|
|
|
|
RSAPUBKEY rsapubkey;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
} PUBRSAKEYSTRUCT_BASE;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContainerIndex, __in DWORD dwFlags,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__inout PCONTAINER_INFO pContainerInfo)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
2013-09-25 19:36:33 +00:00
|
|
|
|
DWORD sz = 0;
|
|
|
|
|
DWORD ret = SCARD_F_UNKNOWN_ERROR;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct md_pkcs15_container *cont = NULL;
|
|
|
|
|
struct sc_pkcs15_der pubkey_der;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
struct sc_pkcs15_prkey_info *prkey_info = NULL;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
int rv;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (!pContainerInfo)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardGetContainerInfo bContainerIndex=%u, dwFlags=0x%08X, " \
|
2010-02-05 13:05:25 +00:00
|
|
|
|
"dwVersion=%u, cbSigPublicKey=%u, cbKeyExPublicKey=%u\n", \
|
|
|
|
|
bContainerIndex, dwFlags, pContainerInfo->dwVersion, \
|
|
|
|
|
pContainerInfo->cbSigPublicKey, pContainerInfo->cbKeyExPublicKey);
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (dwFlags)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (bContainerIndex >= MD_MAX_KEY_CONTAINERS)
|
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
|
|
|
|
if (pContainerInfo->dwVersion < 0 || pContainerInfo->dwVersion > CONTAINER_INFO_CURRENT_VERSION)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
|
|
|
|
|
pContainerInfo->dwVersion = CONTAINER_INFO_CURRENT_VERSION;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
cont = &vs->p15_containers[bContainerIndex];
|
|
|
|
|
|
|
|
|
|
if (!cont->prkey_obj) {
|
|
|
|
|
logprintf(pCardData, 7, "Container %i is empty\n", bContainerIndex);
|
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-10-15 20:40:36 +00:00
|
|
|
|
if (vs->p15card == NULL) {
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
prkey_info = (struct sc_pkcs15_prkey_info *)cont->prkey_obj->data;
|
2015-05-08 13:49:30 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
check_reader_status(pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
pubkey_der.value = NULL;
|
|
|
|
|
pubkey_der.len = 0;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2013-09-25 19:36:33 +00:00
|
|
|
|
if ((cont->prkey_obj->content.value != NULL) && (cont->prkey_obj->content.len > 0)) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
sc_der_copy(&pubkey_der, &cont->prkey_obj->content);
|
2013-09-25 19:36:33 +00:00
|
|
|
|
ret = SCARD_S_SUCCESS;
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pubkey_der.value && cont->pubkey_obj) {
|
|
|
|
|
struct sc_pkcs15_pubkey *pubkey = NULL;
|
|
|
|
|
|
2015-10-04 15:33:14 +00:00
|
|
|
|
logprintf(pCardData, 1, "now read public key '%.*s'\n", (int) sizeof cont->pubkey_obj->label, cont->pubkey_obj->label);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
rv = sc_pkcs15_read_pubkey(vs->p15card, cont->pubkey_obj, &pubkey);
|
|
|
|
|
if (!rv) {
|
2014-02-02 21:16:00 +00:00
|
|
|
|
rv = sc_pkcs15_encode_pubkey(vs->ctx, pubkey, &pubkey_der.value, &pubkey_der.len);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 1, "encode public key error %d\n", rv);
|
|
|
|
|
ret = SCARD_F_INTERNAL_ERROR;
|
2013-09-25 19:36:33 +00:00
|
|
|
|
}
|
2014-05-13 12:57:01 +00:00
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 1, "public key encoded\n");
|
|
|
|
|
ret = SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
sc_pkcs15_free_pubkey(pubkey);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 1, "public key read error %d\n", rv);
|
|
|
|
|
ret = SCARD_E_FILE_NOT_FOUND;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pubkey_der.value && cont->cert_obj) {
|
|
|
|
|
struct sc_pkcs15_cert *cert = NULL;
|
|
|
|
|
|
2015-10-04 15:33:14 +00:00
|
|
|
|
logprintf(pCardData, 1, "now read certificate '%.*s'\n", (int) sizeof cont->cert_obj->label, cont->cert_obj->label);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
rv = sc_pkcs15_read_certificate(vs->p15card, (struct sc_pkcs15_cert_info *)(cont->cert_obj->data), &cert);
|
|
|
|
|
if(!rv) {
|
2014-02-02 21:16:00 +00:00
|
|
|
|
rv = sc_pkcs15_encode_pubkey(vs->ctx, cert->key, &pubkey_der.value, &pubkey_der.len);
|
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 1, "encode certificate public key error %d\n", rv);
|
|
|
|
|
ret = SCARD_F_INTERNAL_ERROR;
|
2013-09-25 19:36:33 +00:00
|
|
|
|
}
|
2014-05-13 12:57:01 +00:00
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 1, "certificate public key encoded\n");
|
|
|
|
|
ret = SCARD_S_SUCCESS;
|
|
|
|
|
}
|
2014-02-02 21:16:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
sc_pkcs15_free_certificate(cert);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 1, "certificate '%d' read error %d\n", bContainerIndex, rv);
|
|
|
|
|
ret = SCARD_E_FILE_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!pubkey_der.value && (cont->size_sign || cont->size_key_exchange)) {
|
|
|
|
|
logprintf(pCardData, 2, "cannot find public key\n");
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 7, "GetContainerInfo(idx:%i) failed; error %X", bContainerIndex, ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 7, "SubjectPublicKeyInfo:\n");
|
|
|
|
|
loghex(pCardData, 7, pubkey_der.value, pubkey_der.len);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if (prkey_info->modulus_length > 0) {
|
|
|
|
|
logprintf(pCardData, 7, "Encoding RSA public key");
|
|
|
|
|
if (pubkey_der.len && pubkey_der.value) {
|
|
|
|
|
sz = 0; /* get size */
|
|
|
|
|
CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
|
|
|
|
|
pubkey_der.value, (DWORD) pubkey_der.len, 0, NULL, &sz);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if (cont->size_sign) {
|
2015-10-15 20:40:36 +00:00
|
|
|
|
PUBRSAKEYSTRUCT_BASE *publicKey = (PUBRSAKEYSTRUCT_BASE *)pCardData->pfnCspAlloc(sz);
|
|
|
|
|
if (!publicKey)
|
2015-09-25 20:22:29 +00:00
|
|
|
|
return SCARD_E_NO_MEMORY;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
|
2015-10-15 20:40:36 +00:00
|
|
|
|
pubkey_der.value, (DWORD) pubkey_der.len, 0, publicKey, &sz);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-10-15 20:40:36 +00:00
|
|
|
|
publicKey->publickeystruc.aiKeyAlg = CALG_RSA_SIGN;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
pContainerInfo->cbSigPublicKey = sz;
|
2015-10-15 20:40:36 +00:00
|
|
|
|
pContainerInfo->pbSigPublicKey = (PBYTE)publicKey;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
logprintf(pCardData, 3, "return info on SIGN_CONTAINER_INDEX %i\n", bContainerIndex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cont->size_key_exchange) {
|
2015-10-15 20:40:36 +00:00
|
|
|
|
PUBRSAKEYSTRUCT_BASE *publicKey = (PUBRSAKEYSTRUCT_BASE*)pCardData->pfnCspAlloc(sz);
|
|
|
|
|
if (!publicKey)
|
2015-09-25 20:22:29 +00:00
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
|
|
|
|
|
CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
|
2015-10-15 20:40:36 +00:00
|
|
|
|
pubkey_der.value, (DWORD) pubkey_der.len, 0, publicKey, &sz);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
|
2015-10-15 20:40:36 +00:00
|
|
|
|
publicKey->publickeystruc.aiKeyAlg = CALG_RSA_KEYX;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
pContainerInfo->cbKeyExPublicKey = sz;
|
2015-10-15 20:40:36 +00:00
|
|
|
|
pContainerInfo->pbKeyExPublicKey = (PBYTE)publicKey;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "return info on KEYX_CONTAINER_INDEX %i\n", bContainerIndex);
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
2015-09-25 20:22:29 +00:00
|
|
|
|
} else if (prkey_info->field_length > 0) {
|
|
|
|
|
logprintf(pCardData, 7, "Encoding ECC public key");
|
|
|
|
|
|
|
|
|
|
if (pubkey_der.len > 2 && pubkey_der.value && pubkey_der.value[0] == 4 && pubkey_der.value[1] == pubkey_der.len -2) {
|
2015-10-15 20:40:36 +00:00
|
|
|
|
BCRYPT_ECCKEY_BLOB *publicKey = NULL;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
DWORD dwMagic = 0;
|
|
|
|
|
if (cont->size_sign) {
|
|
|
|
|
sz = (DWORD) (sizeof(BCRYPT_ECCKEY_BLOB) + pubkey_der.len -3);
|
|
|
|
|
|
|
|
|
|
switch(cont->size_sign)
|
|
|
|
|
{
|
|
|
|
|
case 256:
|
|
|
|
|
dwMagic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
|
|
|
|
|
break;
|
|
|
|
|
case 384:
|
|
|
|
|
dwMagic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC;
|
|
|
|
|
break;
|
|
|
|
|
case 521:
|
|
|
|
|
dwMagic = BCRYPT_ECDSA_PUBLIC_P521_MAGIC;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
logprintf(pCardData, 3, "Unable to match the ECC public size to one of Microsoft algorithm %i\n", cont->size_sign);
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2015-10-15 20:40:36 +00:00
|
|
|
|
publicKey = (BCRYPT_ECCKEY_BLOB *)pCardData->pfnCspAlloc(sz);
|
|
|
|
|
if (!publicKey)
|
2015-09-25 20:22:29 +00:00
|
|
|
|
return SCARD_E_NO_MEMORY;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2015-10-15 20:40:36 +00:00
|
|
|
|
publicKey->cbKey = (DWORD)(pubkey_der.len -3) /2;
|
|
|
|
|
publicKey->dwMagic = dwMagic;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
pContainerInfo->cbSigPublicKey = sz;
|
2015-10-15 20:40:36 +00:00
|
|
|
|
pContainerInfo->pbSigPublicKey = (PBYTE)publicKey;
|
|
|
|
|
memcpy(((PBYTE)publicKey) + sizeof(BCRYPT_ECCKEY_BLOB), pubkey_der.value + 3, pubkey_der.len -3);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "return info on ECC SIGN_CONTAINER_INDEX %i\n", bContainerIndex);
|
|
|
|
|
}
|
|
|
|
|
if (cont->size_key_exchange) {
|
|
|
|
|
sz = (DWORD) (sizeof(BCRYPT_ECCKEY_BLOB) + pubkey_der.len -3);
|
|
|
|
|
|
|
|
|
|
switch(cont->size_key_exchange)
|
|
|
|
|
{
|
|
|
|
|
case 256:
|
|
|
|
|
dwMagic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
|
|
|
|
|
break;
|
|
|
|
|
case 384:
|
|
|
|
|
dwMagic = BCRYPT_ECDH_PUBLIC_P384_MAGIC;
|
|
|
|
|
break;
|
|
|
|
|
case 521:
|
|
|
|
|
dwMagic = BCRYPT_ECDH_PUBLIC_P521_MAGIC;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
logprintf(pCardData, 3, "Unable to match the ECC public size to one of Microsoft algorithm %i\n", cont->size_key_exchange);
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-10-15 20:40:36 +00:00
|
|
|
|
publicKey = (BCRYPT_ECCKEY_BLOB *)pCardData->pfnCspAlloc(sz);
|
|
|
|
|
if (!publicKey)
|
2015-09-25 20:22:29 +00:00
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
|
2015-10-15 20:40:36 +00:00
|
|
|
|
publicKey->cbKey = (DWORD)(pubkey_der.len -3) /2;
|
|
|
|
|
publicKey->dwMagic = dwMagic;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
|
|
|
|
|
pContainerInfo->cbKeyExPublicKey = sz;
|
2015-10-15 20:40:36 +00:00
|
|
|
|
pContainerInfo->pbKeyExPublicKey = (PBYTE)publicKey;
|
|
|
|
|
memcpy(((PBYTE)publicKey) + sizeof(BCRYPT_ECCKEY_BLOB), pubkey_der.value + 3, pubkey_der.len -3);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 3, "return info on ECC KEYX_CONTAINER_INDEX %i\n", bContainerIndex);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 7, "returns container(idx:%i) info", bContainerIndex);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardAuthenticatePin(__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPWSTR pwszUserId,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__in_bcount(cbPin) PBYTE pbPin,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
__in DWORD cbPin,
|
|
|
|
|
__out_opt PDWORD pcAttemptsRemaining)
|
|
|
|
|
{
|
2015-04-17 19:39:41 +00:00
|
|
|
|
PIN_ID PinId = 0;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardAuthenticatePin '%S':%d\n", NULLWSTR(pwszUserId), cbPin);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
if (wcscmp(pwszUserId, wszCARD_USER_USER) == 0) {
|
|
|
|
|
PinId = ROLE_USER;
|
2011-05-11 16:52:13 +00:00
|
|
|
|
}
|
2015-04-17 19:39:41 +00:00
|
|
|
|
else if (wcscmp(pwszUserId, wszCARD_USER_ADMIN) == 0) {
|
|
|
|
|
PinId = ROLE_ADMIN;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2015-04-17 19:39:41 +00:00
|
|
|
|
else {
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
if (pbPin == NULL)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-04-19 17:51:22 +00:00
|
|
|
|
return CardAuthenticateEx(pCardData, PinId, CARD_PIN_SILENT_CONTEXT, pbPin, cbPin, NULL, NULL, pcAttemptsRemaining);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-19 08:34:52 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData,
|
|
|
|
|
__deref_out_bcount(*pcbChallengeData) PBYTE *ppbChallengeData,
|
|
|
|
|
__out PDWORD pcbChallengeData)
|
|
|
|
|
{
|
2013-12-19 08:34:52 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
int rv;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2013-12-19 08:34:52 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardGetChallenge\n");
|
|
|
|
|
|
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (!ppbChallengeData || !pcbChallengeData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 1, "Asked challenge length %i, buffer %p\n", *pcbChallengeData, *ppbChallengeData);
|
2015-04-17 19:39:41 +00:00
|
|
|
|
if (pcbChallengeData == NULL) {
|
2013-12-19 08:34:52 +00:00
|
|
|
|
*ppbChallengeData = NULL;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 7, "returns zero bytes\n");
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
check_reader_status(pCardData);
|
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
*pcbChallengeData = 8;
|
2013-12-19 08:34:52 +00:00
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
*ppbChallengeData = (PBYTE) pCardData->pfnCspAlloc(8);
|
|
|
|
|
if (!*ppbChallengeData)
|
2013-12-19 08:34:52 +00:00
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
rv = sc_get_challenge(vs->p15card->card, *ppbChallengeData, 8);
|
2013-12-19 08:34:52 +00:00
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 1, "Get challenge failed: %s\n", sc_strerror(rv));
|
2015-04-17 19:39:41 +00:00
|
|
|
|
pCardData->pfnCspFree(*ppbChallengeData);
|
|
|
|
|
*ppbChallengeData = NULL;
|
2013-12-19 08:34:52 +00:00
|
|
|
|
return SCARD_E_UNEXPECTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 7, "returns %i bytes:\n", *pcbChallengeData);
|
|
|
|
|
loghex(pCardData, 7, *ppbChallengeData, *pcbChallengeData);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-19 08:34:52 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardAuthenticateChallenge(__in PCARD_DATA pCardData,
|
|
|
|
|
__in_bcount(cbResponseData) PBYTE pbResponseData,
|
|
|
|
|
__in DWORD cbResponseData,
|
|
|
|
|
__out_opt PDWORD pcAttemptsRemaining)
|
|
|
|
|
{
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardAuthenticateChallenge - unsupported\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-19 08:34:52 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPWSTR pwszUserId,
|
|
|
|
|
__in_bcount(cbAuthenticationData) PBYTE pbAuthenticationData,
|
|
|
|
|
__in DWORD cbAuthenticationData,
|
|
|
|
|
__in_bcount(cbNewPinData) PBYTE pbNewPinData,
|
|
|
|
|
__in DWORD cbNewPinData,
|
|
|
|
|
__in DWORD cRetryCount,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
2013-12-19 12:08:03 +00:00
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2013-12-19 12:08:03 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardUnblockPin\n");
|
|
|
|
|
|
|
|
|
|
if (pwszUserId == NULL)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (wcscmp(wszCARD_USER_USER, pwszUserId) != 0 && wcscmp(wszCARD_USER_ADMIN,pwszUserId) != 0)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (wcscmp(wszCARD_USER_ADMIN, pwszUserId) == 0)
|
2015-04-18 17:09:45 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
if (dwFlags & CARD_AUTHENTICATE_PIN_CHALLENGE_RESPONSE)
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
if (dwFlags)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2013-12-19 12:08:03 +00:00
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
logprintf(pCardData, 1, "UserID('%S'), AuthData(%p, %u), NewPIN(%p, %u), Retry(%u), dwFlags(0x%X)\n",
|
2013-12-19 12:08:03 +00:00
|
|
|
|
pwszUserId, pbAuthenticationData, cbAuthenticationData, pbNewPinData, cbNewPinData,
|
|
|
|
|
cRetryCount, dwFlags);
|
|
|
|
|
|
2015-04-19 17:51:22 +00:00
|
|
|
|
return CardChangeAuthenticatorEx(pCardData, PIN_CHANGE_FLAG_UNBLOCK | CARD_PIN_SILENT_CONTEXT, ROLE_ADMIN, pbAuthenticationData, cbAuthenticationData, ROLE_USER, pbNewPinData, cbNewPinData, cRetryCount, NULL);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-19 12:08:03 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPWSTR pwszUserId,
|
|
|
|
|
__in_bcount(cbCurrentAuthenticator) PBYTE pbCurrentAuthenticator,
|
|
|
|
|
__in DWORD cbCurrentAuthenticator,
|
|
|
|
|
__in_bcount(cbNewAuthenticator) PBYTE pbNewAuthenticator,
|
|
|
|
|
__in DWORD cbNewAuthenticator,
|
|
|
|
|
__in DWORD cRetryCount,
|
|
|
|
|
__in DWORD dwFlags,
|
|
|
|
|
__out_opt PDWORD pcAttemptsRemaining)
|
|
|
|
|
{
|
2015-04-18 17:09:45 +00:00
|
|
|
|
PIN_ID pinid;
|
2013-12-22 17:05:32 +00:00
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2013-12-22 17:05:32 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardChangeAuthenticator\n");
|
|
|
|
|
|
|
|
|
|
if (pwszUserId == NULL)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2015-04-18 17:09:45 +00:00
|
|
|
|
if (dwFlags == CARD_AUTHENTICATE_PIN_CHALLENGE_RESPONSE) {
|
2013-12-22 17:05:32 +00:00
|
|
|
|
logprintf(pCardData, 1, "Other then 'authentication' the PIN are not supported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
2015-04-18 17:09:45 +00:00
|
|
|
|
else if (dwFlags != CARD_AUTHENTICATE_PIN_PIN){
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
2013-12-22 17:05:32 +00:00
|
|
|
|
|
|
|
|
|
if (wcscmp(wszCARD_USER_USER, pwszUserId) != 0 && wcscmp(wszCARD_USER_ADMIN, pwszUserId) != 0)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
logprintf(pCardData, 1, "UserID('%S'), CurrentPIN(%p, %u), NewPIN(%p, %u), Retry(%u), dwFlags(0x%X)\n",
|
2013-12-22 17:05:32 +00:00
|
|
|
|
pwszUserId, pbCurrentAuthenticator, cbCurrentAuthenticator, pbNewAuthenticator, cbNewAuthenticator,
|
|
|
|
|
cRetryCount, dwFlags);
|
|
|
|
|
|
|
|
|
|
if (wcscmp(wszCARD_USER_USER, pwszUserId) == 0)
|
2015-04-18 17:09:45 +00:00
|
|
|
|
pinid = ROLE_USER;
|
2013-12-22 17:05:32 +00:00
|
|
|
|
else
|
2015-04-18 17:09:45 +00:00
|
|
|
|
pinid = ROLE_ADMIN;
|
2013-12-22 17:05:32 +00:00
|
|
|
|
|
2015-04-19 17:51:22 +00:00
|
|
|
|
return CardChangeAuthenticatorEx(pCardData, PIN_CHANGE_FLAG_CHANGEPIN | CARD_PIN_SILENT_CONTEXT, pinid, pbCurrentAuthenticator, cbCurrentAuthenticator, pinid, pbNewAuthenticator, cbNewAuthenticator, cRetryCount, pcAttemptsRemaining);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-09 20:29:50 +00:00
|
|
|
|
/* this function is not called on purpose.
|
|
|
|
|
If a deauthentication is not possible, it should be set to NULL in CardAcquireContext.
|
|
|
|
|
Because this function do nothing - it is not called.
|
|
|
|
|
Note: the PIN freshnesh will be managed by the Base CSP*/
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardDeauthenticate(__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPWSTR pwszUserId,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
2015-12-09 20:41:37 +00:00
|
|
|
|
VENDOR_SPECIFIC* vs = NULL;
|
|
|
|
|
int rv;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardDeauthenticate(%S) %d\n", NULLWSTR(pwszUserId), dwFlags);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-12-09 20:41:37 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
sc_pkcs15_pincache_clear(vs->p15card);
|
2015-04-09 20:29:50 +00:00
|
|
|
|
|
2015-12-09 20:41:37 +00:00
|
|
|
|
rv = sc_logout(vs->p15card->card);
|
|
|
|
|
|
|
|
|
|
if (rv != SC_SUCCESS)
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
2015-04-09 20:29:50 +00:00
|
|
|
|
/* force a reset of a card - SCARD_S_SUCCESS do not lead to the reset of the card and leave it still authenticated */
|
2015-12-09 20:41:37 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardCreateDirectory(__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPSTR pszDirectoryName,
|
|
|
|
|
__in CARD_DIRECTORY_ACCESS_CONDITION AccessCondition)
|
|
|
|
|
{
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardCreateDirectory - unsupported\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardDeleteDirectory(__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPSTR pszDirectoryName)
|
|
|
|
|
{
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardDeleteDirectory(%s) - unsupported\n", NULLSTR(pszDirectoryName));
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardCreateFile(__in PCARD_DATA pCardData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__in_opt LPSTR pszDirectoryName,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
__in LPSTR pszFileName,
|
|
|
|
|
__in DWORD cbInitialCreationSize,
|
|
|
|
|
__in CARD_FILE_ACCESS_CONDITION AccessCondition)
|
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct md_directory *dir = NULL;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardCreateFile(%s::%s, size %i, acl:0x%X) called\n",
|
|
|
|
|
NULLSTR(pszDirectoryName), NULLSTR(pszFileName), cbInitialCreationSize, AccessCondition);
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_find_directory(pCardData, NULL, pszDirectoryName, &dir);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 1, "CardCreateFile() cannot find parent directory '%s'", NULLSTR(pszDirectoryName));
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_add_file(pCardData, &dir->files, pszFileName, AccessCondition, NULL, cbInitialCreationSize, NULL);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__in_opt LPSTR pszDirectoryName,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
__in LPSTR pszFileName,
|
|
|
|
|
__in DWORD dwFlags,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__deref_out_bcount_opt(*pcbData) PBYTE *ppbData,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
__out PDWORD pcbData)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct md_directory *dir = NULL;
|
|
|
|
|
struct md_file *file = NULL;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardReadFile\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (!ppbData || !pcbData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
logprintf(pCardData, 2, "pszDirectoryName = %s, pszFileName = %s, dwFlags = %X, pcbData=%u, *ppbData=%X\n",
|
2012-05-31 14:40:36 +00:00
|
|
|
|
NULLSTR(pszDirectoryName), NULLSTR(pszFileName), dwFlags, *pcbData, *ppbData);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pszFileName || !strlen(pszFileName))
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (dwFlags)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
check_reader_status(pCardData);
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
md_fs_find_file(pCardData, pszDirectoryName, pszFileName, &file);
|
|
|
|
|
if (!file) {
|
|
|
|
|
logprintf(pCardData, 2, "CardReadFile(): file '%s' not found in '%s'\n", NULLSTR(pszFileName), NULLSTR(pszDirectoryName));
|
|
|
|
|
return SCARD_E_FILE_NOT_FOUND;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!file->blob)
|
|
|
|
|
md_fs_read_content(pCardData, pszDirectoryName, file);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
*ppbData = pCardData->pfnCspAlloc(file->size);
|
|
|
|
|
if(!*ppbData)
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
2015-04-25 21:29:03 +00:00
|
|
|
|
*pcbData = (DWORD) file->size;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
memcpy(*ppbData, file->blob, file->size);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 7, "returns '%s' content:\n", NULLSTR(pszFileName));
|
|
|
|
|
loghex(pCardData, 7, *ppbData, *pcbData);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
DWORD WINAPI CardWriteFile(__in PCARD_DATA pCardData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__in_opt LPSTR pszDirectoryName,
|
2012-05-31 14:40:36 +00:00
|
|
|
|
__in LPSTR pszFileName,
|
|
|
|
|
__in DWORD dwFlags,
|
|
|
|
|
__in_bcount(cbData) PBYTE pbData,
|
|
|
|
|
__in DWORD cbData)
|
|
|
|
|
{
|
|
|
|
|
struct md_file *file = NULL;
|
|
|
|
|
DWORD dwret;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardWriteFile() dirName:'%s', fileName:'%s' \n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName));
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
check_reader_status(pCardData);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pbData && cbData) {
|
|
|
|
|
logprintf(pCardData, 1, "CardWriteFile try to write (%i):\n", cbData);
|
|
|
|
|
loghex(pCardData, 2, pbData, cbData);
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
md_fs_find_file(pCardData, pszDirectoryName, pszFileName, &file);
|
|
|
|
|
if (!file) {
|
|
|
|
|
logprintf(pCardData, 2, "CardWriteFile(): file '%s' not found in '%s'\n", NULLSTR(pszFileName), NULLSTR(pszDirectoryName));
|
|
|
|
|
return SCARD_E_FILE_NOT_FOUND;
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 7, "set content of '%s' to:\n", NULLSTR(pszFileName));
|
|
|
|
|
loghex(pCardData, 7, pbData, cbData);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = md_fs_set_content(pCardData, file, pbData, cbData);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 1, "cannot set file content: %li\n", dwret);
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pszDirectoryName && !strcmp(pszDirectoryName, "mscp")) {
|
2013-12-29 11:41:36 +00:00
|
|
|
|
if ((strstr(pszFileName, "kxc") == pszFileName) || (strstr(pszFileName, "ksc") == pszFileName)) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = md_pkcs15_store_certificate(pCardData, pszFileName, pbData, cbData);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
|
|
|
|
logprintf(pCardData, 2, "md_pkcs15_store_certificate() OK\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 2, "write '%s' ok.\n", NULLSTR(pszFileName));
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
DWORD WINAPI CardDeleteFile(__in PCARD_DATA pCardData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__in_opt LPSTR pszDirectoryName,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
__in LPSTR pszFileName,
|
2012-05-31 14:40:36 +00:00
|
|
|
|
__in DWORD dwFlags)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct md_file *file = NULL;
|
|
|
|
|
DWORD dwret;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardDeleteFile(%s, %s) called\n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName));
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
|
|
|
|
if(!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
check_reader_status(pCardData);
|
|
|
|
|
|
|
|
|
|
dwret = md_fs_delete_file(pCardData, pszDirectoryName, pszFileName);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "CardDeleteFile(): delete file error: %X\n", dwret);
|
|
|
|
|
return dwret;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardEnumFiles(__in PCARD_DATA pCardData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__in_opt LPSTR pszDirectoryName,
|
|
|
|
|
__deref_out_ecount(*pdwcbFileName) LPSTR *pmszFileNames,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
__out LPDWORD pdwcbFileName,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
|
|
|
|
char mstr[0x100];
|
|
|
|
|
struct md_directory *dir = NULL;
|
|
|
|
|
struct md_file *file = NULL;
|
|
|
|
|
size_t offs;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardEnumFiles() directory '%s'\n", NULLSTR(pszDirectoryName));
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (!pmszFileNames || !pdwcbFileName)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (dwFlags) {
|
|
|
|
|
logprintf(pCardData, 1, "CardEnumFiles() dwFlags not 'zero' -- %X\n", dwFlags);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
memset(mstr, 0, sizeof(mstr));
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-04-12 07:40:12 +00:00
|
|
|
|
if (!pszDirectoryName || !strlen(pszDirectoryName))
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dir = &vs->root;
|
|
|
|
|
else
|
|
|
|
|
md_fs_find_directory(pCardData, NULL, pszDirectoryName, &dir);
|
|
|
|
|
if (!dir) {
|
|
|
|
|
logprintf(pCardData, 2, "enum files() failed: directory '%s' not found\n", NULLSTR(pszDirectoryName));
|
|
|
|
|
return SCARD_E_FILE_NOT_FOUND;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
file = dir->files;
|
|
|
|
|
for (offs = 0; file != NULL && offs < sizeof(mstr) - 10;) {
|
|
|
|
|
logprintf(pCardData, 2, "enum files(): file name '%s'\n", file->name);
|
2015-10-10 20:07:49 +00:00
|
|
|
|
strcpy_s(mstr+offs, sizeof(mstr) - offs, file->name);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
offs += strlen(file->name) + 1;
|
|
|
|
|
file = file->next;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2015-10-10 20:07:49 +00:00
|
|
|
|
mstr[offs] = 0;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
offs += 1;
|
|
|
|
|
|
|
|
|
|
*pmszFileNames = (LPSTR)(*pCardData->pfnCspAlloc)(offs);
|
|
|
|
|
if (*pmszFileNames == NULL)
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
CopyMemory(*pmszFileNames, mstr, offs);
|
2015-04-25 21:29:03 +00:00
|
|
|
|
*pdwcbFileName = (DWORD) offs;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardGetFileInfo(__in PCARD_DATA pCardData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__in_opt LPSTR pszDirectoryName,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
__in LPSTR pszFileName,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__inout PCARD_FILE_INFO pCardFileInfo)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
|
|
|
|
struct md_directory *dir = NULL;
|
|
|
|
|
struct md_file *file = NULL;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardGetFileInfo(dirName:'%s',fileName:'%s', out %p)\n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName), pCardFileInfo);
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
md_fs_find_file(pCardData, pszDirectoryName, pszFileName, &file);
|
|
|
|
|
if (!file) {
|
|
|
|
|
logprintf(pCardData, 2, "CardWriteFile(): file '%s' not found in '%s'\n", NULLSTR(pszFileName), NULLSTR(pszDirectoryName));
|
|
|
|
|
return SCARD_E_FILE_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pCardFileInfo->dwVersion = CARD_FILE_INFO_CURRENT_VERSION;
|
2015-04-25 21:29:03 +00:00
|
|
|
|
pCardFileInfo->cbFileSize = (DWORD) file->size;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
pCardFileInfo->AccessCondition = file->acl;
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardQueryFreeSpace(__in PCARD_DATA pCardData, __in DWORD dwFlags,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__inout PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
DWORD dwret;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardQueryFreeSpace %p, dwFlags=%X, version=%X\n",
|
2010-02-05 13:05:25 +00:00
|
|
|
|
pCardFreeSpaceInfo, dwFlags, pCardFreeSpaceInfo->dwVersion);
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
check_reader_status(pCardData);
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = md_free_space(pCardData, pCardFreeSpaceInfo);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 1, "CardQueryFreeSpace() md free space error");
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 7, "FreeSpace:\n");
|
|
|
|
|
loghex(pCardData, 7, (BYTE *)pCardFreeSpaceInfo, sizeof(*pCardFreeSpaceInfo));
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardQueryKeySizes(__in PCARD_DATA pCardData,
|
|
|
|
|
__in DWORD dwKeySpec,
|
|
|
|
|
__in DWORD dwFlags,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__inout PCARD_KEY_SIZES pKeySizes)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
DWORD dwret;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2015-04-12 12:06:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardQueryKeySizes dwKeySpec=%X, dwFlags=%X, version=%X\n", dwKeySpec, dwFlags, (pKeySizes?pKeySizes->dwVersion:0));
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-04-12 12:06:36 +00:00
|
|
|
|
if ( dwFlags != 0 )
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if ( dwKeySpec == 0 )
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
dwret = md_query_key_sizes(pCardData, dwKeySpec, pKeySizes);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 7, "pKeySizes:\n");
|
|
|
|
|
loghex(pCardData, 7, (BYTE *)pKeySizes, sizeof(*pKeySizes));
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
|
|
|
|
|
__inout PCARD_RSA_DECRYPT_INFO pInfo)
|
|
|
|
|
|
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
int r, opt_crypt_flags = 0;
|
2011-04-07 16:55:07 +00:00
|
|
|
|
unsigned ui;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct sc_pkcs15_prkey_info *prkey_info;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
BYTE *pbuf = NULL, *pbuf2 = NULL;
|
|
|
|
|
DWORD lg= 0, lg2 = 0;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
struct sc_pkcs15_object *pkey = NULL;
|
|
|
|
|
struct sc_algorithm_info *alg_info = NULL;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardRSADecrypt\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (!pInfo)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-04-11 09:08:52 +00:00
|
|
|
|
if ( pInfo->pbData == NULL )
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (pInfo->dwVersion > CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
if ( pInfo->dwVersion < CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION
|
|
|
|
|
&& pCardData->dwVersion == CARD_DATA_CURRENT_VERSION)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
if (pInfo->dwKeySpec != AT_KEYEXCHANGE)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
2015-04-11 09:08:52 +00:00
|
|
|
|
/* check if the container exists */
|
|
|
|
|
if (pInfo->bContainerIndex >= MD_MAX_KEY_CONTAINERS)
|
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
check_reader_status(pCardData);
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 2, "CardRSADecrypt dwVersion=%u, bContainerIndex=%u,dwKeySpec=%u pbData=%p, cbData=%u\n",
|
|
|
|
|
pInfo->dwVersion,pInfo->bContainerIndex ,pInfo->dwKeySpec, pInfo->pbData, pInfo->cbData);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO)
|
|
|
|
|
logprintf(pCardData, 2, " pPaddingInfo=%p dwPaddingType=0x%08X\n", pInfo->pPaddingInfo, pInfo->dwPaddingType);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
pkey = vs->p15_containers[pInfo->bContainerIndex].prkey_obj;
|
|
|
|
|
if (!pkey) {
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 2, "CardRSADecrypt prkey not found\n");
|
2015-04-11 09:08:52 +00:00
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
/* input and output buffers are always the same size */
|
|
|
|
|
pbuf = pCardData->pfnCspAlloc(pInfo->cbData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pbuf)
|
2011-02-09 17:52:00 +00:00
|
|
|
|
return SCARD_E_NO_MEMORY;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
lg2 = pInfo->cbData;
|
|
|
|
|
pbuf2 = pCardData->pfnCspAlloc(pInfo->cbData);
|
2015-04-12 11:34:18 +00:00
|
|
|
|
if (!pbuf2) {
|
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
return SCARD_E_NO_MEMORY;
|
2015-04-12 11:34:18 +00:00
|
|
|
|
}
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
|
|
|
|
/*inversion donnees*/
|
2012-05-31 14:40:36 +00:00
|
|
|
|
for(ui = 0; ui < pInfo->cbData; ui++)
|
|
|
|
|
pbuf[ui] = pInfo->pbData[pInfo->cbData-ui-1];
|
|
|
|
|
logprintf(pCardData, 2, "Data to be decrypted (inverted):\n");
|
|
|
|
|
loghex(pCardData, 7, pbuf, pInfo->cbData);
|
|
|
|
|
|
|
|
|
|
prkey_info = (struct sc_pkcs15_prkey_info *)(pkey->data);
|
2015-04-25 21:29:03 +00:00
|
|
|
|
alg_info = sc_card_find_rsa_alg(vs->p15card->card, (unsigned int) prkey_info->modulus_length);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!alg_info) {
|
|
|
|
|
logprintf(pCardData, 2, "Cannot get appropriate RSA card algorithm for key size %i\n", prkey_info->modulus_length);
|
2015-04-12 11:34:18 +00:00
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
|
|
|
|
pCardData->pfnCspFree(pbuf2);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-11 09:08:52 +00:00
|
|
|
|
/* filter boggus input: the data to decrypt is shorter than the RSA key ? */
|
|
|
|
|
if ( pInfo->cbData < prkey_info->modulus_length / 8)
|
|
|
|
|
{
|
|
|
|
|
/* according to the minidriver specs, this is the error code to return
|
|
|
|
|
(instead of invalid parameter when the call is forwarded to the card implementation) */
|
2015-04-12 11:34:18 +00:00
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
|
|
|
|
pCardData->pfnCspFree(pbuf2);
|
2015-04-11 09:08:52 +00:00
|
|
|
|
return SCARD_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (alg_info->flags & SC_ALGORITHM_RSA_RAW) {
|
2013-05-22 10:11:51 +00:00
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA-RAW mechanism\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags, pbuf, pInfo->cbData, pbuf2, pInfo->cbData);
|
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r);
|
2013-05-22 10:11:51 +00:00
|
|
|
|
|
2015-04-11 09:08:52 +00:00
|
|
|
|
if (r > 0) {
|
|
|
|
|
/* Need to handle padding */
|
|
|
|
|
if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) {
|
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%u\n", pInfo->dwVersion);
|
|
|
|
|
if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) {
|
2015-04-25 21:29:03 +00:00
|
|
|
|
size_t temp = pInfo->cbData;
|
2015-04-11 09:08:52 +00:00
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n");
|
2015-04-25 21:29:03 +00:00
|
|
|
|
r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &temp);
|
|
|
|
|
pInfo->cbData = (DWORD) temp;
|
2015-04-11 09:08:52 +00:00
|
|
|
|
if (r < 0) {
|
|
|
|
|
logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r);
|
2015-04-12 11:34:18 +00:00
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
|
|
|
|
pCardData->pfnCspFree(pbuf2);
|
2015-04-11 09:08:52 +00:00
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (pInfo->dwPaddingType == CARD_PADDING_OAEP) {
|
|
|
|
|
/* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */
|
|
|
|
|
logprintf(pCardData, 2, "OAEP padding not implemented\n");
|
2015-04-12 11:34:18 +00:00
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
|
|
|
|
pCardData->pfnCspFree(pbuf2);
|
2013-05-22 10:11:51 +00:00
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
|
2013-05-22 10:11:51 +00:00
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA_PAD_PKCS1 mechanism\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags | SC_ALGORITHM_RSA_PAD_PKCS1,
|
|
|
|
|
pbuf, pInfo->cbData, pbuf2, pInfo->cbData);
|
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r);
|
|
|
|
|
if (r > 0) {
|
2015-03-28 12:04:41 +00:00
|
|
|
|
/* No padding info, or padding info none */
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if ((pInfo->dwVersion < CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) ||
|
2015-10-16 07:58:01 +00:00
|
|
|
|
((pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) && (pInfo->dwPaddingType == CARD_PADDING_NONE))) {
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if ((unsigned)r <= pInfo->cbData - 9) {
|
|
|
|
|
/* add pkcs1 02 padding */
|
|
|
|
|
logprintf(pCardData, 2, "Add '%s' to the output data", "PKCS#1 BT02 padding");
|
|
|
|
|
memset(pbuf, 0x30, pInfo->cbData);
|
|
|
|
|
*(pbuf + 0) = 0;
|
|
|
|
|
*(pbuf + 1) = 2;
|
|
|
|
|
memcpy(pbuf + pInfo->cbData - r, pbuf2, r);
|
|
|
|
|
*(pbuf + pInfo->cbData - r - 1) = 0;
|
|
|
|
|
memcpy(pbuf2, pbuf, pInfo->cbData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) {
|
2015-03-28 12:04:41 +00:00
|
|
|
|
/* PKCS1 padding is already handled by the card... */
|
2012-05-31 14:40:36 +00:00
|
|
|
|
pInfo->cbData = r;
|
|
|
|
|
}
|
|
|
|
|
/* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 2, "CardRSADecrypt: no usable RSA algorithm\n");
|
2015-04-12 11:34:18 +00:00
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
|
|
|
|
pCardData->pfnCspFree(pbuf2);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if ( r < 0) {
|
2013-05-22 10:11:51 +00:00
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r));
|
2015-04-12 11:34:18 +00:00
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
|
|
|
|
pCardData->pfnCspFree(pbuf2);
|
2015-04-19 17:51:22 +00:00
|
|
|
|
return md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 2, "decrypted data(%i):\n", pInfo->cbData);
|
|
|
|
|
loghex(pCardData, 7, pbuf2, pInfo->cbData);
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
/*inversion donnees */
|
2012-05-31 14:40:36 +00:00
|
|
|
|
for(ui = 0; ui < pInfo->cbData; ui++)
|
|
|
|
|
pInfo->pbData[ui] = pbuf2[pInfo->cbData-ui-1];
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
|
|
|
|
pCardData->pfnCspFree(pbuf2);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO pInfo)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
ALG_ID hashAlg;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
sc_pkcs15_prkey_info_t *prkey_info;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
BYTE dataToSign[0x200];
|
2011-04-07 16:55:07 +00:00
|
|
|
|
int r, opt_crypt_flags = 0, opt_hash_flags = 0;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
size_t dataToSignLen = sizeof(dataToSign);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
sc_pkcs15_object_t *pkey;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardSignData\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData || !pInfo)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-04-09 20:02:10 +00:00
|
|
|
|
if ( ( pInfo->dwVersion != CARD_SIGNING_INFO_BASIC_VERSION ) &&
|
|
|
|
|
( pInfo->dwVersion != CARD_SIGNING_INFO_CURRENT_VERSION ) )
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
if ( pInfo->pbData == NULL )
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
switch(pInfo->dwKeySpec)
|
|
|
|
|
{
|
|
|
|
|
case AT_SIGNATURE:
|
|
|
|
|
case AT_KEYEXCHANGE:
|
|
|
|
|
case AT_ECDSA_P256:
|
|
|
|
|
case AT_ECDSA_P384:
|
|
|
|
|
case AT_ECDSA_P521:
|
|
|
|
|
case AT_ECDHE_P256:
|
|
|
|
|
case AT_ECDHE_P384:
|
|
|
|
|
case AT_ECDHE_P521:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2015-04-09 20:02:10 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
}
|
2015-04-18 13:23:18 +00:00
|
|
|
|
if (pInfo->dwSigningFlags & ~(CARD_PADDING_INFO_PRESENT | CARD_PADDING_NONE | CARD_BUFFER_SIZE_ONLY | CARD_PADDING_PKCS1 | CARD_PADDING_PSS | CARD_PADDING_OAEP))
|
2015-04-09 20:02:10 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 2, "CardSignData dwVersion=%u, bContainerIndex=%u, dwKeySpec=%u, dwSigningFlags=0x%08X, aiHashAlg=0x%08X\n",
|
|
|
|
|
pInfo->dwVersion,pInfo->bContainerIndex ,pInfo->dwKeySpec, pInfo->dwSigningFlags, pInfo->aiHashAlg);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-03-23 18:37:46 +00:00
|
|
|
|
logprintf(pCardData, 7, "pInfo->pbData(%i) ", pInfo->cbData);
|
|
|
|
|
loghex(pCardData, 7, pInfo->pbData, pInfo->cbData);
|
|
|
|
|
|
|
|
|
|
hashAlg = pInfo->aiHashAlg;
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pInfo->bContainerIndex >= MD_MAX_KEY_CONTAINERS)
|
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
pkey = vs->p15_containers[pInfo->bContainerIndex].prkey_obj;
|
|
|
|
|
if (!pkey)
|
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
|
|
|
|
prkey_info = (struct sc_pkcs15_prkey_info *)(pkey->data);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
check_reader_status(pCardData);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 2, "pInfo->dwVersion = %d\n", pInfo->dwVersion);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (dataToSignLen < pInfo->cbData)
|
|
|
|
|
return SCARD_E_INSUFFICIENT_BUFFER;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
memcpy(dataToSign, pInfo->pbData, pInfo->cbData);
|
|
|
|
|
dataToSignLen = pInfo->cbData;
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (CARD_PADDING_INFO_PRESENT & pInfo->dwSigningFlags) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
BCRYPT_PKCS1_PADDING_INFO *pinf = (BCRYPT_PKCS1_PADDING_INFO *)pInfo->pPaddingInfo;
|
2015-04-09 20:02:10 +00:00
|
|
|
|
if (CARD_PADDING_PSS == pInfo->dwPaddingType) {
|
|
|
|
|
logprintf(pCardData, 0, "unsupported paddingtype CARD_PADDING_PSS\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
2015-04-09 20:02:10 +00:00
|
|
|
|
else if (CARD_PADDING_PKCS1 != pInfo->dwPaddingType) {
|
|
|
|
|
logprintf(pCardData, 0, "unsupported paddingtype\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pinf->pszAlgId) {
|
2010-06-11 07:35:45 +00:00
|
|
|
|
/* hashAlg = CALG_SSL3_SHAMD5; */
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 3, "Using CALG_SSL3_SHAMD5 hashAlg\n");
|
2011-03-23 18:37:46 +00:00
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5_SHA1;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else {
|
|
|
|
|
if (wcscmp(pinf->pszAlgId, L"MD5") == 0)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5;
|
|
|
|
|
else if (wcscmp(pinf->pszAlgId, L"SHA1") == 0)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA1;
|
|
|
|
|
else if (wcscmp(pinf->pszAlgId, L"SHAMD5") == 0)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5_SHA1;
|
2015-04-11 12:17:20 +00:00
|
|
|
|
else if (wcscmp(pinf->pszAlgId, L"SHA224") == 0)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA224;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(pinf->pszAlgId, L"SHA256") == 0)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA256;
|
2015-04-11 12:17:20 +00:00
|
|
|
|
else if (wcscmp(pinf->pszAlgId, L"SHA384") == 0)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA384;
|
|
|
|
|
else if (wcscmp(pinf->pszAlgId, L"SHA512") == 0)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA512;
|
|
|
|
|
else if (wcscmp(pinf->pszAlgId, L"RIPEMD160") == 0)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_RIPEMD160;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
else
|
2012-05-31 14:40:36 +00:00
|
|
|
|
{
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 0,"unknown AlgId %S\n",NULLWSTR(pinf->pszAlgId));
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else {
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 3, "CARD_PADDING_INFO_PRESENT not set\n");
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
|
|
|
|
if (hashAlg == CALG_MD5)
|
2011-03-23 18:37:46 +00:00
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
else if (hashAlg == CALG_SHA1)
|
2011-03-23 18:37:46 +00:00
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA1;
|
|
|
|
|
else if (hashAlg == CALG_SSL3_SHAMD5)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5_SHA1;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (hashAlg == CALG_SHA_256)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA256;
|
2015-04-11 12:17:20 +00:00
|
|
|
|
else if (hashAlg == CALG_SHA_384)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA384;
|
|
|
|
|
else if (hashAlg == CALG_SHA_512)
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA512;
|
|
|
|
|
else if (hashAlg == (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_RIPEMD160))
|
|
|
|
|
opt_hash_flags = SC_ALGORITHM_RSA_HASH_RIPEMD160;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
else if (hashAlg !=0) {
|
|
|
|
|
logprintf(pCardData, 0, "bogus aiHashAlg %i\n", hashAlg);
|
2011-03-23 18:37:46 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2015-04-11 06:52:22 +00:00
|
|
|
|
|
|
|
|
|
if (pInfo->dwSigningFlags & CARD_PADDING_NONE)
|
|
|
|
|
{
|
|
|
|
|
/* do not add the digest info when called from CryptSignHash(CRYPT_NOHASHOID)
|
|
|
|
|
|
|
|
|
|
Note: SC_ALGORITHM_RSA_HASH_MD5_SHA1 aka CALG_SSL3_SHAMD5 do not have a digest info to be added
|
|
|
|
|
CryptSignHash(CALG_SSL3_SHAMD5,CRYPT_NOHASHOID) is the same than CryptSignHash(CALG_SSL3_SHAMD5)
|
|
|
|
|
*/
|
|
|
|
|
opt_hash_flags = 0;
|
|
|
|
|
}
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
|
|
|
|
/* From sc-minidriver_specs_v7.docx pp.76:
|
2011-04-12 07:40:12 +00:00
|
|
|
|
* 'The Base CSP/KSP performs the hashing operation on the data before passing it
|
2012-05-31 14:40:36 +00:00
|
|
|
|
* to CardSignData for signature.'
|
|
|
|
|
* So, the SC_ALGORITHM_RSA_HASH_* flags should not be passed to pkcs15 library
|
|
|
|
|
* when calculating the signature .
|
2011-03-23 18:37:46 +00:00
|
|
|
|
*
|
|
|
|
|
* From sc-minidriver_specs_v7.docx pp.76:
|
2011-04-12 07:40:12 +00:00
|
|
|
|
* 'If the aiHashAlg member is nonzero, it specifies the hash algorithm’s object identifier (OID)
|
2011-03-23 18:37:46 +00:00
|
|
|
|
* that is encoded in the PKCS padding.'
|
|
|
|
|
* So, the digest info has be included into the data to be signed.
|
|
|
|
|
* */
|
|
|
|
|
if (opt_hash_flags) {
|
|
|
|
|
logprintf(pCardData, 2, "include digest info of the algorithm 0x%08X\n", opt_hash_flags);
|
|
|
|
|
dataToSignLen = sizeof(dataToSign);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
r = sc_pkcs1_encode(vs->ctx, opt_hash_flags, pInfo->pbData, pInfo->cbData, dataToSign, &dataToSignLen, 0);
|
2011-03-23 18:37:46 +00:00
|
|
|
|
if (r) {
|
|
|
|
|
logprintf(pCardData, 2, "PKCS#1 encode error %s\n", sc_strerror(r));
|
|
|
|
|
return SCARD_E_INVALID_VALUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
/* Compute output size */
|
|
|
|
|
if ( prkey_info->modulus_length > 0) {
|
|
|
|
|
/* RSA */
|
|
|
|
|
pInfo->cbSignedData = (DWORD) prkey_info->modulus_length / 8;
|
|
|
|
|
opt_crypt_flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE;
|
|
|
|
|
} else if ( prkey_info->field_length > 0) {
|
|
|
|
|
opt_crypt_flags = SC_ALGORITHM_ECDSA_HASH_NONE;
|
|
|
|
|
switch(prkey_info->field_length) {
|
|
|
|
|
case 256:
|
|
|
|
|
/* ECDSA_P256 */
|
|
|
|
|
pInfo->cbSignedData = 256 / 8 * 2;
|
|
|
|
|
break;
|
|
|
|
|
case 384:
|
|
|
|
|
/* ECDSA_P384 */
|
|
|
|
|
pInfo->cbSignedData = 384 / 8 * 2;
|
|
|
|
|
break;
|
|
|
|
|
case 512:
|
|
|
|
|
/* ECDSA_P512 : special case !!!*/
|
|
|
|
|
pInfo->cbSignedData = 132;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
logprintf(pCardData, 0, "unknown ECC key size %i\n", prkey_info->field_length);
|
|
|
|
|
return SCARD_E_INVALID_VALUE;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
logprintf(pCardData, 0, "invalid private key\n");
|
|
|
|
|
return SCARD_E_INVALID_VALUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 3, "pInfo->cbSignedData = %d\n", pInfo->cbSignedData);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(!(pInfo->dwSigningFlags&CARD_BUFFER_SIZE_ONLY)) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
int r,i;
|
2011-03-23 18:37:46 +00:00
|
|
|
|
BYTE *pbuf = NULL;
|
|
|
|
|
DWORD lg;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
lg = pInfo->cbSignedData;
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 3, "lg = %d\n", lg);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
pbuf = pCardData->pfnCspAlloc(lg);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
if (!pbuf)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_NO_MEMORY;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-03-23 18:37:46 +00:00
|
|
|
|
logprintf(pCardData, 7, "Data to sign: ");
|
|
|
|
|
loghex(pCardData, 7, dataToSign, dataToSignLen);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
pInfo->pbSignedData = (PBYTE) pCardData->pfnCspAlloc(pInfo->cbSignedData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pInfo->pbSignedData) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
r = sc_pkcs15_compute_signature(vs->p15card, pkey, opt_crypt_flags, dataToSign, dataToSignLen, pbuf, lg);
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_compute_signature return %d\n", r);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(r < 0) {
|
2016-05-12 11:15:31 +00:00
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_compute_signature error %s\n", sc_strerror(r));
|
2015-04-12 11:34:18 +00:00
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
2015-04-19 17:51:22 +00:00
|
|
|
|
return md_translate_OpenSC_to_Windows_error(r, SCARD_F_INTERNAL_ERROR);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pInfo->cbSignedData = r;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
|
|
|
|
|
/*revert data only for RSA (Microsoft uses the big endian version while everyone is using little endian*/
|
|
|
|
|
if ( prkey_info->modulus_length > 0) {
|
|
|
|
|
for(i = 0; i < r; i++)
|
|
|
|
|
pInfo->pbSignedData[i] = pbuf[r-i-1];
|
|
|
|
|
} else {
|
|
|
|
|
for(i = 0; i < r; i++)
|
|
|
|
|
pInfo->pbSignedData[i] = pbuf[i];
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
pCardData->pfnCspFree(pbuf);
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 7, "Signature (inverted): ");
|
2011-02-09 17:52:00 +00:00
|
|
|
|
loghex(pCardData, 7, pInfo->pbSignedData, pInfo->cbSignedData);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 3, "CardSignData, dwVersion=%u, name=%S, hScard=0x%08X, hSCardCtx=0x%08X\n",
|
|
|
|
|
pCardData->dwVersion, NULLWSTR(pCardData->pwszCardName),pCardData->hScard, pCardData->hSCardCtx);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardConstructDHAgreement(__in PCARD_DATA pCardData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__inout PCARD_DH_AGREEMENT_INFO pAgreementInfo)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
2015-09-25 20:22:29 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct sc_pkcs15_object *pkey = NULL;
|
|
|
|
|
int r, opt_derive_flags = 0;
|
|
|
|
|
u8* out = 0;
|
|
|
|
|
unsigned long outlen = 0;
|
|
|
|
|
PBYTE pbPublicKey = NULL;
|
|
|
|
|
DWORD dwPublicKeySize = 0;
|
|
|
|
|
struct md_dh_agreement* dh_agreement = NULL;
|
|
|
|
|
struct md_dh_agreement* temp = NULL;
|
|
|
|
|
BYTE i;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardConstructDHAgreement\n");
|
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (!pAgreementInfo)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if ( pAgreementInfo->pbPublicKey == NULL )
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (pAgreementInfo->dwVersion > CARD_DH_AGREEMENT_INFO_VERSION)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
if ( pAgreementInfo->dwVersion < CARD_DH_AGREEMENT_INFO_VERSION
|
|
|
|
|
&& pCardData->dwVersion == CARD_DATA_CURRENT_VERSION)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
/* check if the container exists */
|
|
|
|
|
if (pAgreementInfo->bContainerIndex >= MD_MAX_KEY_CONTAINERS)
|
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
|
|
|
|
|
|
|
|
|
check_reader_status(pCardData);
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 2, "CardConstructDHAgreement dwVersion=%u, dwKeySpec=%u pbData=%p, cbData=%u\n",
|
|
|
|
|
pAgreementInfo->dwVersion,pAgreementInfo->bContainerIndex , pAgreementInfo->pbPublicKey, pAgreementInfo->dwPublicKey);
|
|
|
|
|
|
|
|
|
|
pkey = vs->p15_containers[pAgreementInfo->bContainerIndex].prkey_obj;
|
|
|
|
|
if (!pkey) {
|
|
|
|
|
logprintf(pCardData, 2, "CardConstructDHAgreement prkey not found\n");
|
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* convert the Windows public key into an OpenSC public key */
|
|
|
|
|
dwPublicKeySize = pAgreementInfo->dwPublicKey - sizeof(BCRYPT_ECCKEY_BLOB) + 1;
|
|
|
|
|
pbPublicKey = (PBYTE) pCardData->pfnCspAlloc(dwPublicKeySize);
|
|
|
|
|
if (!pbPublicKey) {
|
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pbPublicKey[0] = 4;
|
|
|
|
|
memcpy(pbPublicKey+1, pAgreementInfo->pbPublicKey + sizeof(BCRYPT_ECCKEY_BLOB), dwPublicKeySize-1);
|
|
|
|
|
|
|
|
|
|
/* derive the key using the OpenSC functions */
|
|
|
|
|
r = sc_pkcs15_derive(vs->p15card, pkey, opt_derive_flags, pbPublicKey, dwPublicKeySize, out, &outlen );
|
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_derive returned %d\n", r);
|
|
|
|
|
|
|
|
|
|
if ( r < 0) {
|
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_derive error(%i): %s\n", r, sc_strerror(r));
|
|
|
|
|
pCardData->pfnCspFree(pbPublicKey);
|
|
|
|
|
return md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out = pCardData->pfnCspAlloc(outlen);
|
|
|
|
|
|
|
|
|
|
if (!out) {
|
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = sc_pkcs15_derive(vs->p15card, pkey, opt_derive_flags, pbPublicKey, dwPublicKeySize, out, &outlen );
|
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_derive returned %d\n", r);
|
|
|
|
|
|
|
|
|
|
pCardData->pfnCspFree(pbPublicKey);
|
|
|
|
|
|
|
|
|
|
if ( r < 0) {
|
|
|
|
|
logprintf(pCardData, 2, "sc_pkcs15_derive error(%i): %s\n", r, sc_strerror(r));
|
|
|
|
|
pCardData->pfnCspFree(out);
|
|
|
|
|
return md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* save the dh agreement for later use */
|
|
|
|
|
|
|
|
|
|
/* try to find an empty index */
|
|
|
|
|
for (i = 0; i < vs->allocatedAgreements; i++) {
|
|
|
|
|
dh_agreement = vs->dh_agreements + i;
|
|
|
|
|
if (dh_agreement->pbAgreement == NULL) {
|
|
|
|
|
pAgreementInfo->bSecretAgreementIndex = i;
|
|
|
|
|
dh_agreement->pbAgreement = out;
|
|
|
|
|
dh_agreement->dwSize = outlen;
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* no empty space => need to allocate memory */
|
|
|
|
|
temp = (struct md_dh_agreement*) pCardData->pfnCspAlloc((vs->allocatedAgreements+1) * sizeof(struct md_dh_agreement));
|
|
|
|
|
if (!temp) {
|
|
|
|
|
pCardData->pfnCspFree(out);
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
if ((vs->allocatedAgreements) > 0) {
|
|
|
|
|
memcpy(temp, vs->dh_agreements, sizeof(struct md_dh_agreement) * (vs->allocatedAgreements));
|
|
|
|
|
pCardData->pfnCspFree(vs->dh_agreements);
|
|
|
|
|
}
|
|
|
|
|
vs->dh_agreements = temp;
|
|
|
|
|
dh_agreement = vs->dh_agreements + (vs->allocatedAgreements);
|
|
|
|
|
pAgreementInfo->bSecretAgreementIndex = (vs->allocatedAgreements);
|
|
|
|
|
dh_agreement->pbAgreement = out;
|
|
|
|
|
dh_agreement->dwSize = outlen;
|
|
|
|
|
vs->allocatedAgreements++;
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardDeriveHashOrHMAC(__in PCARD_DATA pCardData,
|
|
|
|
|
__inout PCARD_DERIVE_KEY pAgreementInfo,
|
|
|
|
|
__in struct md_dh_agreement* agreement,
|
|
|
|
|
__in PWSTR szAlgorithm,
|
|
|
|
|
__in PBYTE pbHmacKey, __in DWORD dwHmacKeySize
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwReturn = 0;
|
|
|
|
|
/* CNG variables */
|
|
|
|
|
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
|
|
|
|
|
BCRYPT_HASH_HANDLE hHash = NULL;
|
|
|
|
|
DWORD dwSize, dwHashSize;
|
|
|
|
|
PBYTE pbBuffer = NULL;
|
|
|
|
|
DWORD dwBufferSize = 0;
|
|
|
|
|
ULONG i;
|
|
|
|
|
NCryptBufferDesc* parameters = NULL;
|
|
|
|
|
|
|
|
|
|
dwReturn = BCryptOpenAlgorithmProvider(&hAlgorithm, szAlgorithm, NULL, (pbHmacKey?BCRYPT_ALG_HANDLE_HMAC_FLAG:0));
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to find a provider for the algorithm %S 0x%08X\n", szAlgorithm, dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
|
dwReturn = BCryptGetProperty(hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&dwHashSize, dwSize, &dwSize, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to get the hash length\n");
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
pAgreementInfo->cbDerivedKey = dwHashSize;
|
|
|
|
|
if (pAgreementInfo->dwFlags & CARD_BUFFER_SIZE_ONLY) {
|
|
|
|
|
dwReturn = SCARD_S_SUCCESS;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
pAgreementInfo->pbDerivedKey = (PBYTE)pCardData->pfnCspAlloc(dwHashSize);
|
|
|
|
|
if (pAgreementInfo->pbDerivedKey == NULL) {
|
|
|
|
|
dwReturn = SCARD_E_NO_MEMORY;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
|
dwReturn = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&dwBufferSize, dwSize, &dwSize, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to get the buffer length 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pbBuffer = (PBYTE)LocalAlloc(0, dwBufferSize);
|
|
|
|
|
if (pbBuffer == NULL) {
|
|
|
|
|
dwReturn = SCARD_E_NO_MEMORY;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HMAC) == 0) {
|
|
|
|
|
dwReturn = BCryptCreateHash(hAlgorithm, &hHash, pbBuffer, dwBufferSize, pbHmacKey, dwHmacKeySize, 0);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
dwReturn = BCryptCreateHash(hAlgorithm, &hHash, pbBuffer, dwBufferSize, NULL, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to create the alg object 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parameters = (NCryptBufferDesc*) pAgreementInfo->pParameterList;
|
|
|
|
|
if (parameters) {
|
|
|
|
|
for (i = 0; i < parameters->cBuffers; i++) {
|
|
|
|
|
NCryptBuffer* buffer = parameters->pBuffers + i;
|
|
|
|
|
if (buffer->BufferType == KDF_SECRET_PREPEND) {
|
|
|
|
|
dwReturn = BCryptHashData(hHash, (PUCHAR)buffer->pvBuffer, buffer->cbBuffer, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to hash data 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwReturn = BCryptHashData(hHash, (PUCHAR)agreement->pbAgreement, agreement->dwSize, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to hash data 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parameters) {
|
|
|
|
|
for (i = 0; i < parameters->cBuffers; i++) {
|
|
|
|
|
NCryptBuffer* buffer = parameters->pBuffers + i;
|
|
|
|
|
if (buffer->BufferType == KDF_SECRET_APPEND) {
|
|
|
|
|
dwReturn = BCryptHashData(hHash, (PUCHAR)buffer->pvBuffer, buffer->cbBuffer, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to hash data 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwReturn = BCryptFinishHash(hHash, pAgreementInfo->pbDerivedKey, pAgreementInfo->cbDerivedKey, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to finish hash 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
|
|
|
|
|
if (hHash)
|
|
|
|
|
BCryptDestroyHash(hHash);
|
|
|
|
|
if (pbBuffer)
|
|
|
|
|
LocalFree(pbBuffer);
|
|
|
|
|
if (hAlgorithm)
|
|
|
|
|
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
|
|
|
|
|
return dwReturn;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 20:56:26 +00:00
|
|
|
|
/* Generic function to perform hash. Could have been OpenSSL but used BCrypt* functions.
|
|
|
|
|
BCrypt is loaded as a delay load library. The dll can be loaded into Windows XP until this code is called.
|
|
|
|
|
Hopefully, ECC is not available in Windows XP and BCrypt functions are not called */
|
2015-10-14 20:48:41 +00:00
|
|
|
|
DWORD HashDataWithBCrypt(__in PCARD_DATA pCardData, BCRYPT_ALG_HANDLE hAlgorithm,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
PBYTE pbOuput, DWORD dwOutputSize, PBYTE pbSecret, DWORD dwSecretSize,
|
|
|
|
|
PBYTE pbData1, DWORD dwDataSize1,
|
|
|
|
|
PBYTE pbData2, DWORD dwDataSize2,
|
|
|
|
|
PBYTE pbData3, DWORD dwDataSize3 )
|
2015-09-25 20:22:29 +00:00
|
|
|
|
{
|
|
|
|
|
DWORD dwReturn, dwSize, dwBufferSize;
|
|
|
|
|
BCRYPT_HASH_HANDLE hHash = NULL;
|
|
|
|
|
PBYTE pbBuffer = NULL;
|
|
|
|
|
|
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
|
dwReturn = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&dwBufferSize, dwSize, &dwSize, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to get the buffer length 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
pbBuffer = (PBYTE)LocalAlloc(0, dwBufferSize);
|
|
|
|
|
if (pbBuffer == NULL) {
|
|
|
|
|
dwReturn = SCARD_E_NO_MEMORY;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
dwReturn = BCryptCreateHash(hAlgorithm, &hHash, pbBuffer, dwBufferSize, pbSecret, dwSecretSize, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to create the alg object 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
if (pbData1) {
|
|
|
|
|
dwReturn = BCryptHashData(hHash, pbData1, dwDataSize1, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to hash data 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pbData2) {
|
|
|
|
|
dwReturn = BCryptHashData(hHash, pbData2, dwDataSize2, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to hash data 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pbData3) {
|
|
|
|
|
dwReturn = BCryptHashData(hHash, pbData3, dwDataSize3, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to hash data 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dwReturn = BCryptFinishHash(hHash, pbOuput, dwOutputSize, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to finish hash 0x%08X\n", dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
cleanup:
|
|
|
|
|
if (hHash)
|
|
|
|
|
BCryptDestroyHash(hHash);
|
|
|
|
|
if (pbBuffer)
|
|
|
|
|
LocalFree(pbBuffer);
|
|
|
|
|
return dwReturn;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 20:56:26 +00:00
|
|
|
|
/* Generic function for TLS PRF. Compute the P_HASH function */
|
2015-09-25 20:22:29 +00:00
|
|
|
|
DWORD WINAPI DoTlsPrf(__in PCARD_DATA pCardData,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
__in PBYTE pbOutput,
|
2015-09-25 20:22:29 +00:00
|
|
|
|
__in PBYTE pbSecret,
|
|
|
|
|
__in DWORD dwSecretSize,
|
|
|
|
|
__in PWSTR szAlgorithm,
|
|
|
|
|
__in PBYTE pbLabel, __in DWORD dwLabelSize,
|
|
|
|
|
__in PBYTE pbSeed
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwReturn = 0, i;
|
|
|
|
|
/* CNG variables */
|
|
|
|
|
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
|
|
|
|
|
DWORD dwSize, dwHashSize, dwNumberOfRounds, dwLastRoundSize;
|
|
|
|
|
PBYTE pbBuffer = NULL;
|
|
|
|
|
/* TLS intermediate results */
|
|
|
|
|
PBYTE pbAx = NULL;
|
|
|
|
|
|
|
|
|
|
dwReturn = BCryptOpenAlgorithmProvider(&hAlgorithm, szAlgorithm, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to find a provider for the algorithm %S 0x%08X\n", szAlgorithm, dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
|
dwReturn = BCryptGetProperty(hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&dwHashSize, dwSize, &dwSize, 0);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to get the hash length\n");
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* size is always 48 */
|
2015-10-14 20:48:41 +00:00
|
|
|
|
dwLastRoundSize = TLS_DERIVE_KEY_SIZE % dwHashSize;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if (dwLastRoundSize == 0) dwLastRoundSize = dwHashSize;
|
2015-10-14 20:48:41 +00:00
|
|
|
|
dwNumberOfRounds = (DWORD) (TLS_DERIVE_KEY_SIZE / dwHashSize) + (dwLastRoundSize == dwHashSize?0:1);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
|
|
|
|
|
/* store TLS A1, A2 intermediate operations */
|
|
|
|
|
pbAx = (PBYTE) LocalAlloc(0, dwNumberOfRounds * dwHashSize);
|
|
|
|
|
if (pbAx == NULL) {
|
|
|
|
|
dwReturn = SCARD_E_NO_MEMORY;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pbBuffer = (PBYTE) LocalAlloc(0, dwHashSize);
|
|
|
|
|
if (pbBuffer == NULL) {
|
|
|
|
|
dwReturn = SCARD_E_NO_MEMORY;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i<dwNumberOfRounds; i++) {
|
|
|
|
|
/* A1, A2, ... */
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
/* A(1) = HMAC_hash(secret, label + seed)*/
|
2015-10-14 20:48:41 +00:00
|
|
|
|
dwReturn = HashDataWithBCrypt(pCardData, hAlgorithm,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
pbAx, dwHashSize, pbSecret, dwSecretSize,
|
|
|
|
|
pbLabel, dwLabelSize,
|
|
|
|
|
pbSeed, 64,
|
|
|
|
|
NULL, 0);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
} else {
|
|
|
|
|
/* A(i) = HMAC_hash(secret, A(i-1))*/
|
2015-10-14 20:48:41 +00:00
|
|
|
|
dwReturn = HashDataWithBCrypt(pCardData, hAlgorithm,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
pbAx + i * dwHashSize, dwHashSize, pbSecret, dwSecretSize,
|
|
|
|
|
pbAx + (i-1) * dwHashSize, dwHashSize,
|
|
|
|
|
NULL, 0,
|
|
|
|
|
NULL, 0);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
}
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to hash Ax 0x%08X\n", szAlgorithm, dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
if (dwNumberOfRounds -1 == i) {
|
|
|
|
|
/* last round */
|
2015-10-14 20:48:41 +00:00
|
|
|
|
dwReturn = HashDataWithBCrypt(pCardData, hAlgorithm,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
pbBuffer, dwHashSize, pbSecret, dwSecretSize,
|
|
|
|
|
pbAx + i * dwHashSize, dwHashSize,
|
|
|
|
|
pbLabel, dwLabelSize,
|
|
|
|
|
pbSeed, 64);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
memcpy(pbOutput + i * dwHashSize, pbBuffer, dwLastRoundSize);
|
|
|
|
|
} else {
|
2015-10-14 20:48:41 +00:00
|
|
|
|
dwReturn = HashDataWithBCrypt(pCardData, hAlgorithm,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
pbOutput + i * dwHashSize, dwHashSize, pbSecret, dwSecretSize,
|
|
|
|
|
pbAx + i * dwHashSize, dwHashSize,
|
|
|
|
|
pbLabel, dwLabelSize,
|
|
|
|
|
pbSeed, 64);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
}
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unable to hash Ax 0x%08X\n", szAlgorithm, dwReturn);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
if (pbBuffer)
|
|
|
|
|
LocalFree(pbBuffer);
|
|
|
|
|
if (pbAx)
|
|
|
|
|
LocalFree(pbAx);
|
|
|
|
|
if (hAlgorithm)
|
|
|
|
|
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
|
|
|
|
|
return dwReturn;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 20:56:26 +00:00
|
|
|
|
/* Implement TLS 1.0, 1.1 and 1.2 PRF */
|
2015-09-25 20:22:29 +00:00
|
|
|
|
DWORD WINAPI CardDeriveTlsPrf(__in PCARD_DATA pCardData,
|
|
|
|
|
__inout PCARD_DERIVE_KEY pAgreementInfo,
|
|
|
|
|
__in struct md_dh_agreement* agreement,
|
|
|
|
|
__in DWORD dwProtocol,
|
|
|
|
|
__in PWSTR szAlgorithm,
|
|
|
|
|
__in PBYTE pbLabel, __in DWORD dwLabelSize,
|
|
|
|
|
__in PBYTE pbSeed
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwReturn = 0;
|
|
|
|
|
PBYTE pbBuffer = NULL;
|
|
|
|
|
DWORD i;
|
|
|
|
|
if(dwProtocol == 0) {
|
2015-10-14 20:48:41 +00:00
|
|
|
|
dwProtocol = TLS1_0_PROTOCOL_VERSION;
|
|
|
|
|
} else if (dwProtocol == TLS1_0_PROTOCOL_VERSION || dwProtocol == TLS1_1_PROTOCOL_VERSION) {
|
2015-09-25 20:22:29 +00:00
|
|
|
|
/* TLS 1.0 & 1.1 */
|
2015-10-14 20:48:41 +00:00
|
|
|
|
} else if (dwProtocol == TLS1_2_PROTOCOL_VERSION) {
|
2015-09-25 20:22:29 +00:00
|
|
|
|
/* TLS 1.2 */
|
|
|
|
|
if (szAlgorithm && wcscmp(szAlgorithm, BCRYPT_SHA256_ALGORITHM) != 0 && wcscmp(szAlgorithm, BCRYPT_SHA384_ALGORITHM) != 0) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: The algorithm for TLS_PRF is invalid %S\n", szAlgorithm);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveTlsPrf: TLS protocol unknwon 0x%08X\n", dwReturn);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
/* size is always 48 according to msdn */
|
2015-10-14 20:48:41 +00:00
|
|
|
|
pAgreementInfo->cbDerivedKey = TLS_DERIVE_KEY_SIZE;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if (pAgreementInfo->dwFlags & CARD_BUFFER_SIZE_ONLY) {
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-14 20:48:41 +00:00
|
|
|
|
pAgreementInfo->pbDerivedKey = (PBYTE)pCardData->pfnCspAlloc(TLS_DERIVE_KEY_SIZE);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if (pAgreementInfo->pbDerivedKey == NULL) {
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-14 20:48:41 +00:00
|
|
|
|
if (dwProtocol == TLS1_0_PROTOCOL_VERSION || dwProtocol == TLS1_1_PROTOCOL_VERSION) {
|
2015-09-25 20:22:29 +00:00
|
|
|
|
/* TLS 1.0 & 1.1 */
|
|
|
|
|
DWORD dwNewSecretLength = (((agreement->dwSize) + (2) - 1) / (2));
|
|
|
|
|
dwReturn = DoTlsPrf(pCardData,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
pAgreementInfo->pbDerivedKey,
|
2015-09-25 20:22:29 +00:00
|
|
|
|
agreement->pbAgreement,
|
|
|
|
|
dwNewSecretLength,
|
|
|
|
|
BCRYPT_MD5_ALGORITHM,
|
|
|
|
|
pbLabel, dwLabelSize,
|
|
|
|
|
pbSeed);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveTlsPrf: unable to DoTlsPrf with %S 0x%08X\n", szAlgorithm, dwReturn);
|
|
|
|
|
pCardData->pfnCspFree(pAgreementInfo->pbDerivedKey );
|
|
|
|
|
pAgreementInfo->pbDerivedKey = NULL;
|
|
|
|
|
return dwReturn;
|
|
|
|
|
}
|
2015-10-14 20:48:41 +00:00
|
|
|
|
pbBuffer = (PBYTE) LocalAlloc(0, TLS_DERIVE_KEY_SIZE);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if (!pbBuffer) {
|
|
|
|
|
pCardData->pfnCspFree(pAgreementInfo->pbDerivedKey );
|
|
|
|
|
pAgreementInfo->pbDerivedKey = NULL;
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
dwReturn = DoTlsPrf(pCardData,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
pbBuffer,
|
2015-09-25 20:22:29 +00:00
|
|
|
|
agreement->pbAgreement + dwNewSecretLength,
|
|
|
|
|
dwNewSecretLength,
|
|
|
|
|
BCRYPT_SHA1_ALGORITHM,
|
|
|
|
|
pbLabel, dwLabelSize,
|
|
|
|
|
pbSeed);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveTlsPrf: unable to DoTlsPrf with %S 0x%08X\n", szAlgorithm, dwReturn);
|
|
|
|
|
LocalFree(pbBuffer);
|
|
|
|
|
pCardData->pfnCspFree(pAgreementInfo->pbDerivedKey );
|
|
|
|
|
pAgreementInfo->pbDerivedKey = NULL;
|
|
|
|
|
return dwReturn;
|
|
|
|
|
}
|
2015-10-14 20:48:41 +00:00
|
|
|
|
for (i = 0; i< TLS_DERIVE_KEY_SIZE; i++) {
|
2015-09-25 20:22:29 +00:00
|
|
|
|
pAgreementInfo->pbDerivedKey[i] = pAgreementInfo->pbDerivedKey[i] ^ pbBuffer[i];
|
|
|
|
|
}
|
|
|
|
|
LocalFree(pbBuffer);
|
|
|
|
|
|
2015-10-14 20:48:41 +00:00
|
|
|
|
} else if (dwProtocol == TLS1_2_PROTOCOL_VERSION) {
|
2015-09-25 20:22:29 +00:00
|
|
|
|
dwReturn = DoTlsPrf(pCardData,
|
2015-10-16 07:58:01 +00:00
|
|
|
|
pAgreementInfo->pbDerivedKey,
|
2015-09-25 20:22:29 +00:00
|
|
|
|
agreement->pbAgreement,
|
|
|
|
|
agreement->dwSize,
|
|
|
|
|
szAlgorithm,
|
|
|
|
|
pbLabel, dwLabelSize,
|
|
|
|
|
pbSeed);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveTlsPrf: unable to DoTlsPrf with %S 0x%08X\n", szAlgorithm, dwReturn);
|
|
|
|
|
pCardData->pfnCspFree(pAgreementInfo->pbDerivedKey );
|
|
|
|
|
pAgreementInfo->pbDerivedKey = NULL;
|
|
|
|
|
return dwReturn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__inout PCARD_DERIVE_KEY pAgreementInfo)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
2015-09-25 20:22:29 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
DWORD dwAgreementIndex = 0;
|
|
|
|
|
struct md_dh_agreement* agreement = NULL;
|
|
|
|
|
NCryptBufferDesc* parameters = NULL;
|
|
|
|
|
ULONG i;
|
|
|
|
|
DWORD dwReturn = 0;
|
|
|
|
|
/* store parameter references */
|
|
|
|
|
PWSTR szAlgorithm = NULL;
|
|
|
|
|
PBYTE pbHmacKey = NULL;
|
|
|
|
|
DWORD dwHmacKeySize = 0;
|
|
|
|
|
PBYTE pbLabel = NULL;
|
|
|
|
|
DWORD dwLabelSize = 0;
|
|
|
|
|
PBYTE pbSeed = NULL;
|
|
|
|
|
DWORD dwProtocol = 0;
|
|
|
|
|
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardDeriveKey\n");
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (!pAgreementInfo)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-09-30 20:49:41 +00:00
|
|
|
|
if (!pAgreementInfo->dwVersion)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
if (pAgreementInfo->dwVersion > CARD_DERIVE_KEY_CURRENT_VERSION)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
2015-09-30 20:49:41 +00:00
|
|
|
|
if (pAgreementInfo->pwszKDF == NULL)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (pAgreementInfo->dwFlags & ~(KDF_USE_SECRET_AS_HMAC_KEY_FLAG | CARD_RETURN_KEY_HANDLE | CARD_BUFFER_SIZE_ONLY))
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
/* according to the documenation, CARD_DERIVE_KEY_CURRENT_VERSION should be equal to 2.
|
|
|
|
|
In pratice it is not 2 but 1
|
|
|
|
|
|
|
|
|
|
if ( pAgreementInfo->dwVersion < CARD_DERIVE_KEY_CURRENT_VERSION
|
|
|
|
|
&& pCardData->dwVersion == CARD_DATA_CURRENT_VERSION)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;*/
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
/* check if the agreement index is ok */
|
|
|
|
|
if (pAgreementInfo->bSecretAgreementIndex >= vs->allocatedAgreements) {
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
agreement = vs->dh_agreements + pAgreementInfo->bSecretAgreementIndex;
|
|
|
|
|
if (agreement->pbAgreement == NULL) {
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pAgreementInfo->dwFlags & CARD_RETURN_KEY_HANDLE ) {
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* find the algorithm, checks parameters */
|
|
|
|
|
|
|
|
|
|
parameters = (NCryptBufferDesc*)pAgreementInfo->pParameterList;
|
|
|
|
|
|
|
|
|
|
if (parameters) {
|
|
|
|
|
for (i = 0; i < parameters->cBuffers; i++) {
|
|
|
|
|
NCryptBuffer* buffer = parameters->pBuffers + i;
|
|
|
|
|
switch(buffer->BufferType) {
|
|
|
|
|
case KDF_HASH_ALGORITHM:
|
|
|
|
|
if (szAlgorithm != NULL) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: got more than one algorithm\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_SHA1_ALGORITHM) == 0) {
|
|
|
|
|
szAlgorithm = BCRYPT_SHA1_ALGORITHM;
|
|
|
|
|
} else if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_SHA256_ALGORITHM) == 0) {
|
|
|
|
|
szAlgorithm = BCRYPT_SHA256_ALGORITHM;
|
|
|
|
|
} else if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_SHA384_ALGORITHM) == 0) {
|
2015-09-30 20:49:41 +00:00
|
|
|
|
szAlgorithm = BCRYPT_SHA384_ALGORITHM;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
} else if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_SHA512_ALGORITHM) == 0) {
|
2015-09-30 20:49:41 +00:00
|
|
|
|
szAlgorithm = BCRYPT_SHA512_ALGORITHM;
|
2015-09-25 20:22:29 +00:00
|
|
|
|
} else if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_MD5_ALGORITHM) == 0) {
|
|
|
|
|
szAlgorithm = BCRYPT_MD5_ALGORITHM;
|
|
|
|
|
} else {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unsupported algorithm %S\n", buffer->pvBuffer);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case KDF_HMAC_KEY:
|
|
|
|
|
if (pbHmacKey != NULL) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: got more than one hhmac key\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
pbHmacKey = (PBYTE) buffer->pvBuffer;
|
|
|
|
|
dwHmacKeySize = buffer->cbBuffer;
|
|
|
|
|
break;
|
|
|
|
|
case KDF_SECRET_APPEND:
|
|
|
|
|
case KDF_SECRET_PREPEND:
|
|
|
|
|
/* do not throw an error for invalid arg*/
|
|
|
|
|
break;
|
|
|
|
|
case KDF_TLS_PRF_LABEL:
|
|
|
|
|
if (pbLabel != NULL) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: got more than one Label\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
pbLabel = (PBYTE)buffer->pvBuffer;
|
|
|
|
|
dwLabelSize = buffer->cbBuffer;
|
|
|
|
|
break;
|
|
|
|
|
case KDF_TLS_PRF_SEED:
|
|
|
|
|
if (pbSeed != NULL) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: got more than one Seed\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
if (buffer->cbBuffer != 64)
|
|
|
|
|
{
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: invalid seed size %u\n", buffer->cbBuffer);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
pbSeed = (PBYTE)buffer->pvBuffer;
|
|
|
|
|
break;
|
|
|
|
|
case KDF_TLS_PRF_PROTOCOL:
|
|
|
|
|
dwProtocol = *((PDWORD)buffer->pvBuffer);
|
|
|
|
|
break;
|
|
|
|
|
/*case KDF_ALGORITHMID:
|
|
|
|
|
case KDF_PARTYUINFO:
|
|
|
|
|
case KDF_PARTYVINFO:
|
|
|
|
|
case KDF_SUPPPUBINFO:
|
|
|
|
|
case KDF_SUPPPRIVINFO:
|
|
|
|
|
break;*/
|
|
|
|
|
default:
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unknown buffer type %u\n", (parameters->pBuffers + i)->BufferType);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* default parameters */
|
|
|
|
|
if (szAlgorithm == NULL && wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_TLS_PRF) != 0) {
|
|
|
|
|
szAlgorithm = BCRYPT_SHA1_ALGORITHM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check the values with the KDF choosen */
|
|
|
|
|
if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HASH) == 0) {
|
|
|
|
|
}
|
|
|
|
|
else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HMAC) == 0) {
|
|
|
|
|
if (pbHmacKey == NULL) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: no hhmac key for hmac KDF\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_TLS_PRF) == 0) {
|
|
|
|
|
if (!pbSeed) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: No seed was provided\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
if (!pbLabel) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: No label was provided\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: unsupported KDF %S\n", pAgreementInfo->pwszKDF);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do the job for the KDF Hash & Hmac */
|
|
|
|
|
if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HASH) == 0 ||
|
|
|
|
|
wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HMAC) == 0 ) {
|
|
|
|
|
|
|
|
|
|
dwReturn = CardDeriveHashOrHMAC(pCardData, pAgreementInfo, agreement, szAlgorithm, pbHmacKey, dwHmacKeySize);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: got an error while deriving the Key (hash or HMAC) 0x%08X\n", dwReturn);
|
|
|
|
|
return dwReturn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_TLS_PRF) == 0) {
|
|
|
|
|
dwReturn = CardDeriveTlsPrf(pCardData, pAgreementInfo, agreement, dwProtocol, szAlgorithm, pbLabel, dwLabelSize, pbSeed);
|
|
|
|
|
if (dwReturn) {
|
|
|
|
|
logprintf(pCardData, 0, "CardDeriveKey: got an error while deriving the Key (TlsPrf) 0x%08X\n", dwReturn);
|
|
|
|
|
return dwReturn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_SP80056A_CONCAT ) == 0) {
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardDestroyDHAgreement(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in BYTE bSecretAgreementIndex,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
2015-09-25 20:22:29 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
struct md_dh_agreement* agreement = NULL;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2015-09-25 20:22:29 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardDestroyDHAgreement\n");
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (dwFlags)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
if (bSecretAgreementIndex >= vs->allocatedAgreements) {
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
agreement = vs->dh_agreements + bSecretAgreementIndex;
|
|
|
|
|
if (agreement->pbAgreement == NULL) {
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
SecureZeroMemory(agreement->pbAgreement, agreement->dwSize);
|
|
|
|
|
pCardData->pfnCspFree(agreement->pbAgreement);
|
|
|
|
|
agreement->pbAgreement = 0;
|
|
|
|
|
agreement->dwSize = 0;
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardGetChallengeEx(__in PCARD_DATA pCardData,
|
|
|
|
|
__in PIN_ID PinId,
|
|
|
|
|
__deref_out_bcount(*pcbChallengeData) PBYTE *ppbChallengeData,
|
|
|
|
|
__out PDWORD pcbChallengeData,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardGetChallengeEx - unsupported\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData,
|
|
|
|
|
__in PIN_ID PinId,
|
|
|
|
|
__in DWORD dwFlags,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__in_bcount(cbPinData) PBYTE pbPinData,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
__in DWORD cbPinData,
|
2015-04-17 19:39:41 +00:00
|
|
|
|
__deref_opt_out_bcount(*pcbSessionPin) PBYTE *ppbSessionPin,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
__out_opt PDWORD pcbSessionPin,
|
|
|
|
|
__out_opt PDWORD pcAttemptsRemaining)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2013-12-18 13:15:02 +00:00
|
|
|
|
struct sc_pkcs15_object *pin_obj = NULL;
|
|
|
|
|
struct sc_pkcs15_auth_info *auth_info = NULL;
|
2014-01-19 17:42:25 +00:00
|
|
|
|
int r;
|
2015-04-19 17:51:22 +00:00
|
|
|
|
BOOL DisplayPinpadUI = FALSE;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardAuthenticateEx\n");
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 2, "CardAuthenticateEx: PinId=%u, dwFlags=0x%08X, cbPinData=%u, Attempts %s\n",
|
2013-12-22 17:05:32 +00:00
|
|
|
|
PinId, dwFlags, cbPinData, pcAttemptsRemaining ? "YES" : "NO");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
2015-05-08 13:49:30 +00:00
|
|
|
|
r = check_reader_status(pCardData);
|
|
|
|
|
|
|
|
|
|
if ((vs->p15card) == NULL)
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2013-09-24 16:07:03 +00:00
|
|
|
|
if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN || dwFlags == CARD_AUTHENTICATE_SESSION_PIN) {
|
|
|
|
|
if (! (vs->reader->capabilities & SC_READER_CAP_PIN_PAD))
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
2013-12-18 13:15:02 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
if (dwFlags & ~(CARD_AUTHENTICATE_GENERATE_SESSION_PIN | CARD_AUTHENTICATE_SESSION_PIN | CARD_PIN_SILENT_CONTEXT))
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
/* using a pin pad */
|
|
|
|
|
if (NULL == pbPinData) {
|
|
|
|
|
if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD))
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2016-12-09 11:54:06 +00:00
|
|
|
|
if (!(dwFlags & CARD_PIN_SILENT_CONTEXT)
|
|
|
|
|
&& !(vs->ctx->flags & SC_CTX_FLAG_DISABLE_POPUPS)) {
|
2015-04-19 17:51:22 +00:00
|
|
|
|
DisplayPinpadUI = TRUE;
|
2015-04-17 19:39:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (PinId != ROLE_USER)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2013-12-18 13:15:02 +00:00
|
|
|
|
if(pcAttemptsRemaining)
|
2015-04-17 14:39:48 +00:00
|
|
|
|
(*pcAttemptsRemaining) = (DWORD) -1;
|
2013-12-18 13:15:02 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
r = md_get_pin_by_role(pCardData, PinId, &pin_obj);
|
|
|
|
|
if (r != SCARD_S_SUCCESS) {
|
2011-03-23 18:37:46 +00:00
|
|
|
|
logprintf(pCardData, 2, "Cannot get User PIN object");
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-18 13:15:02 +00:00
|
|
|
|
if (!pin_obj)
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
|
|
|
|
|
|
2013-09-24 16:07:03 +00:00
|
|
|
|
/* Do we need to display a prompt to enter PIN on pin pad? */
|
2015-04-17 19:39:41 +00:00
|
|
|
|
logprintf(pCardData, 7, "PIN pad=%s, pbPinData=%p, hwndParent=%p\n",
|
2013-09-24 16:07:03 +00:00
|
|
|
|
vs->reader->capabilities & SC_READER_CAP_PIN_PAD ? "yes" : "no", pbPinData, vs->hwndParent);
|
2013-12-25 22:18:29 +00:00
|
|
|
|
|
2015-04-20 21:25:57 +00:00
|
|
|
|
/* check if the pin is the session pin generated by a previous authentication with a pinpad */
|
|
|
|
|
if (pbPinData != NULL && cbPinData == sizeof(MAGIC_SESSION_PIN) && memcmp(MAGIC_SESSION_PIN, pbPinData, sizeof(MAGIC_SESSION_PIN)) == 0) {
|
|
|
|
|
pbPinData = NULL;
|
|
|
|
|
cbPinData = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-19 17:51:22 +00:00
|
|
|
|
r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_VERIFY, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, NULL, 0, DisplayPinpadUI);
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (r) {
|
2013-12-18 13:15:02 +00:00
|
|
|
|
logprintf(pCardData, 1, "PIN code verification failed: %s; tries left %i\n", sc_strerror(r), auth_info->tries_left);
|
|
|
|
|
|
2015-04-17 21:04:39 +00:00
|
|
|
|
if (r == SC_ERROR_AUTH_METHOD_BLOCKED) {
|
2015-04-18 13:26:42 +00:00
|
|
|
|
if(pcAttemptsRemaining)
|
|
|
|
|
(*pcAttemptsRemaining) = 0;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_W_CHV_BLOCKED;
|
2015-04-17 21:04:39 +00:00
|
|
|
|
}
|
2013-12-18 13:15:02 +00:00
|
|
|
|
|
2011-04-12 07:40:12 +00:00
|
|
|
|
if(pcAttemptsRemaining)
|
2013-12-18 13:15:02 +00:00
|
|
|
|
(*pcAttemptsRemaining) = auth_info->tries_left;
|
2015-04-19 17:51:22 +00:00
|
|
|
|
return md_translate_OpenSC_to_Windows_error(r, SCARD_W_WRONG_CHV);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 2, "Pin code correct.\n");
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-04-20 21:25:57 +00:00
|
|
|
|
/* set the session pin according to the minidriver specification */
|
|
|
|
|
if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN && (vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) {
|
|
|
|
|
/* we set it to a special value for pinpad authentication to force a new pinpad authentication */
|
|
|
|
|
if (pcbSessionPin) *pcbSessionPin = sizeof(MAGIC_SESSION_PIN);
|
|
|
|
|
if (ppbSessionPin) {
|
|
|
|
|
*ppbSessionPin = pCardData->pfnCspAlloc(sizeof(MAGIC_SESSION_PIN));
|
|
|
|
|
if (ppbSessionPin) memcpy(*ppbSessionPin, MAGIC_SESSION_PIN, sizeof(MAGIC_SESSION_PIN));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (pcbSessionPin) *pcbSessionPin = 0;
|
|
|
|
|
if (ppbSessionPin) *ppbSessionPin = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData,
|
|
|
|
|
__in DWORD dwFlags,
|
|
|
|
|
__in PIN_ID dwAuthenticatingPinId,
|
|
|
|
|
__in_bcount(cbAuthenticatingPinData) PBYTE pbAuthenticatingPinData,
|
|
|
|
|
__in DWORD cbAuthenticatingPinData,
|
|
|
|
|
__in PIN_ID dwTargetPinId,
|
|
|
|
|
__in_bcount(cbTargetData) PBYTE pbTargetData,
|
|
|
|
|
__in DWORD cbTargetData,
|
|
|
|
|
__in DWORD cRetryCount,
|
|
|
|
|
__out_opt PDWORD pcAttemptsRemaining)
|
|
|
|
|
{
|
2015-04-18 17:09:45 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
|
|
|
|
DWORD dw_rv;
|
|
|
|
|
struct sc_pkcs15_object *pin_obj = NULL;
|
|
|
|
|
int rv;
|
|
|
|
|
struct sc_pkcs15_auth_info *auth_info;
|
2015-04-19 17:51:22 +00:00
|
|
|
|
BOOL DisplayPinpadUI = FALSE;
|
2015-04-06 17:38:15 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2015-04-18 17:09:45 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardChangeAuthenticatorEx\n");
|
2015-04-06 17:38:15 +00:00
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-04-18 17:09:45 +00:00
|
|
|
|
if (!(dwFlags & PIN_CHANGE_FLAG_UNBLOCK) && !(dwFlags & PIN_CHANGE_FLAG_CHANGEPIN)){
|
|
|
|
|
logprintf(pCardData, 1, "Unknown flag\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
if ((dwFlags & PIN_CHANGE_FLAG_UNBLOCK) && (dwFlags & PIN_CHANGE_FLAG_CHANGEPIN))
|
2015-04-06 17:38:15 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-04-18 17:09:45 +00:00
|
|
|
|
if (dwFlags & PIN_CHANGE_FLAG_UNBLOCK && dwAuthenticatingPinId == dwTargetPinId)
|
2015-04-06 17:38:15 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (dwAuthenticatingPinId != ROLE_USER && dwAuthenticatingPinId != ROLE_ADMIN)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-04-18 17:09:45 +00:00
|
|
|
|
if (dwTargetPinId != ROLE_USER && dwTargetPinId != ROLE_ADMIN) {
|
|
|
|
|
logprintf(pCardData, 1, "Only ROLE_USER or ROLE_ADMIN is supported\n");
|
2015-04-06 17:38:15 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-04-18 17:09:45 +00:00
|
|
|
|
}
|
2015-04-06 17:38:15 +00:00
|
|
|
|
/* according to the spec: cRetryCount MUST be zero */
|
|
|
|
|
if (cRetryCount)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 2, "CardChangeAuthenticatorEx: AuthenticatingPinId=%u, dwFlags=0x%08X, cbAuthenticatingPinData=%u, TargetPinId=%u, cbTargetData=%u, Attempts %s\n",
|
|
|
|
|
dwAuthenticatingPinId, dwFlags, cbAuthenticatingPinData, dwTargetPinId, cbTargetData, pcAttemptsRemaining ? "YES" : "NO");
|
|
|
|
|
|
2015-04-18 17:09:45 +00:00
|
|
|
|
|
|
|
|
|
check_reader_status(pCardData);
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
|
|
|
|
if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) {
|
|
|
|
|
if (pbAuthenticatingPinData == NULL || cbAuthenticatingPinData == 0) {
|
|
|
|
|
logprintf(pCardData, 1, "Invalid current PIN data\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pbTargetData == NULL || cbTargetData == 0) {
|
|
|
|
|
logprintf(pCardData, 1, "Invalid new PIN data\n");
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
2015-04-06 17:38:15 +00:00
|
|
|
|
}
|
2015-04-18 17:09:45 +00:00
|
|
|
|
/* using a pin pad */
|
|
|
|
|
if (NULL == pbAuthenticatingPinData) {
|
2016-12-09 11:54:06 +00:00
|
|
|
|
if (!(dwFlags & CARD_PIN_SILENT_CONTEXT)
|
|
|
|
|
&& !(vs->ctx->flags & SC_CTX_FLAG_DISABLE_POPUPS)) {
|
2015-04-19 17:51:22 +00:00
|
|
|
|
DisplayPinpadUI = TRUE;
|
2015-04-18 17:09:45 +00:00
|
|
|
|
}
|
2015-04-06 17:38:15 +00:00
|
|
|
|
}
|
2015-04-18 17:09:45 +00:00
|
|
|
|
|
|
|
|
|
dw_rv = md_get_pin_by_role(pCardData, dwTargetPinId, &pin_obj);
|
|
|
|
|
if (dw_rv != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "Cannot get User PIN object %s", (dwTargetPinId==ROLE_ADMIN?"admin":"user"));
|
|
|
|
|
return dw_rv;
|
|
|
|
|
}
|
|
|
|
|
if (!pin_obj)
|
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
|
|
|
|
|
|
if(pcAttemptsRemaining)
|
|
|
|
|
(*pcAttemptsRemaining) = (DWORD) -1;
|
|
|
|
|
|
2015-04-19 17:51:22 +00:00
|
|
|
|
rv = md_dialog_perform_pin_operation(pCardData, (dwFlags & PIN_CHANGE_FLAG_UNBLOCK ? SC_PIN_CMD_UNBLOCK:SC_PIN_CMD_CHANGE),
|
|
|
|
|
vs->p15card, pin_obj, (const u8 *) pbAuthenticatingPinData, cbAuthenticatingPinData, pbTargetData, cbTargetData, DisplayPinpadUI);
|
|
|
|
|
|
2015-04-18 17:09:45 +00:00
|
|
|
|
if (rv) {
|
|
|
|
|
logprintf(pCardData, 2, "Failed to %s %s PIN: '%s' (%i)\n",
|
|
|
|
|
(dwFlags & PIN_CHANGE_FLAG_CHANGEPIN?"change":"unblock"),
|
|
|
|
|
(dwTargetPinId==ROLE_ADMIN?"admin":"user"), sc_strerror(rv), rv);
|
|
|
|
|
auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
|
|
|
|
|
if (rv == SC_ERROR_AUTH_METHOD_BLOCKED) {
|
|
|
|
|
if(pcAttemptsRemaining)
|
|
|
|
|
(*pcAttemptsRemaining) = 0;
|
|
|
|
|
return SCARD_W_CHV_BLOCKED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(pcAttemptsRemaining)
|
|
|
|
|
(*pcAttemptsRemaining) = auth_info->tries_left;
|
2015-04-19 17:51:22 +00:00
|
|
|
|
return md_translate_OpenSC_to_Windows_error(rv, SCARD_W_WRONG_CHV);
|
2015-04-18 17:09:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logprintf(pCardData, 7, "returns success\n");
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardDeauthenticateEx(__in PCARD_DATA pCardData,
|
|
|
|
|
__in PIN_SET PinId,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardDeauthenticateEx PinId=%d dwFlags=0x%08X\n",PinId, dwFlags);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-12-09 20:41:37 +00:00
|
|
|
|
return CardDeauthenticate(pCardData, wszCARD_USER_USER, 0);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData,
|
|
|
|
|
__in BYTE bContainerIndex,
|
|
|
|
|
__in LPCWSTR wszProperty,
|
|
|
|
|
__out_bcount_part_opt(cbData, *pdwDataLen) PBYTE pbData,
|
|
|
|
|
__in DWORD cbData,
|
|
|
|
|
__out PDWORD pdwDataLen,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
2015-04-12 12:06:36 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs = NULL;
|
|
|
|
|
struct md_pkcs15_container *cont = NULL;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardGetContainerProperty\n");
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
|
|
|
|
check_reader_status(pCardData);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
if (!pCardData) return SCARD_E_INVALID_PARAMETER;
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 2, "CardGetContainerProperty bContainerIndex=%u, wszProperty=%S," \
|
2010-02-05 13:05:25 +00:00
|
|
|
|
"cbData=%u, dwFlags=0x%08X\n",bContainerIndex,NULLWSTR(wszProperty),cbData,dwFlags);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!wszProperty)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (dwFlags)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (!pbData || !pdwDataLen)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-04-12 12:06:36 +00:00
|
|
|
|
if (bContainerIndex >= MD_MAX_KEY_CONTAINERS)
|
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
|
|
|
|
|
|
|
|
|
/* the test for the existence of containers is redondant with the one made in CardGetContainerInfo but CCP_PIN_IDENTIFIER does not do it */
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
cont = &vs->p15_containers[bContainerIndex];
|
|
|
|
|
|
|
|
|
|
if (!cont->prkey_obj) {
|
|
|
|
|
logprintf(pCardData, 7, "Container %i is empty\n", bContainerIndex);
|
|
|
|
|
return SCARD_E_NO_KEY_CONTAINER;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (wcscmp(CCP_CONTAINER_INFO,wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
PCONTAINER_INFO p = (PCONTAINER_INFO) pbData;
|
|
|
|
|
if (pdwDataLen) *pdwDataLen = sizeof(*p);
|
|
|
|
|
if (cbData >= sizeof(DWORD))
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (p->dwVersion != CONTAINER_INFO_CURRENT_VERSION && p->dwVersion != 0 )
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return CardGetContainerInfo(pCardData,bContainerIndex,0,p);
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (wcscmp(CCP_PIN_IDENTIFIER,wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
PPIN_ID p = (PPIN_ID) pbData;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*p);
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
*p = ROLE_USER;
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 2,"Return Pin id %u\n",*p);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardSetContainerProperty(__in PCARD_DATA pCardData,
|
|
|
|
|
__in BYTE bContainerIndex,
|
|
|
|
|
__in LPCWSTR wszProperty,
|
|
|
|
|
__in_bcount(cbDataLen) PBYTE pbData,
|
|
|
|
|
__in DWORD cbDataLen,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardSetContainerProperty - unsupported\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPCWSTR wszProperty,
|
|
|
|
|
__out_bcount_part_opt(cbData, *pdwDataLen) PBYTE pbData,
|
|
|
|
|
__in DWORD cbData,
|
|
|
|
|
__out PDWORD pdwDataLen,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
DWORD dwret;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 2, "CardGetProperty('%S',cbData=%u,dwFlags=%u) called\n", NULLWSTR(wszProperty),cbData,dwFlags);
|
|
|
|
|
|
|
|
|
|
if (!pCardData || !wszProperty)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (!pbData || !pdwDataLen)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
check_reader_status(pCardData);
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (wcscmp(CP_CARD_FREE_SPACE,wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo = (PCARD_FREE_SPACE_INFO )pbData;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*pCardFreeSpaceInfo);
|
|
|
|
|
if (cbData < sizeof(*pCardFreeSpaceInfo))
|
|
|
|
|
return SCARD_E_NO_MEMORY;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = md_free_space(pCardData, pCardFreeSpaceInfo);
|
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 1, "Get free space error");
|
|
|
|
|
return dwret;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(CP_CARD_CAPABILITIES, wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
PCARD_CAPABILITIES pCardCapabilities = (PCARD_CAPABILITIES )pbData;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*pCardCapabilities);
|
|
|
|
|
if (cbData < sizeof(*pCardCapabilities))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
2015-04-17 16:04:05 +00:00
|
|
|
|
dwret = md_card_capabilities(pCardData, pCardCapabilities);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(CP_CARD_KEYSIZES,wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
PCARD_KEY_SIZES pKeySizes = (PCARD_KEY_SIZES )pbData;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*pKeySizes);
|
|
|
|
|
if (cbData < sizeof(*pKeySizes))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-09-25 20:22:29 +00:00
|
|
|
|
dwret = md_query_key_sizes(pCardData, 0, pKeySizes);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (dwret != SCARD_S_SUCCESS)
|
|
|
|
|
return dwret;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(CP_CARD_READ_ONLY, wszProperty) == 0) {
|
|
|
|
|
BOOL *p = (BOOL *)pbData;
|
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*p);
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
*p = md_is_read_only(pCardData);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(CP_CARD_CACHE_MODE, wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD *p = (DWORD *)pbData;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*p);
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
*p = CP_CACHE_MODE_NO_CACHE;
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(CP_SUPPORTS_WIN_X509_ENROLLMENT, wszProperty) == 0) {
|
|
|
|
|
BOOL *p = (BOOL *)pbData;
|
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*p);
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
*p = md_is_supports_X509_enrollment(pCardData);
|
|
|
|
|
}
|
|
|
|
|
else if (wcscmp(CP_CARD_GUID, wszProperty) == 0) {
|
|
|
|
|
struct md_file *cardid = NULL;
|
|
|
|
|
|
|
|
|
|
md_fs_find_file(pCardData, NULL, "cardid", &cardid);
|
|
|
|
|
if (!cardid) {
|
|
|
|
|
logprintf(pCardData, 2, "file 'cardid' not found\n");
|
|
|
|
|
return SCARD_E_FILE_NOT_FOUND;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pdwDataLen)
|
2015-04-25 21:29:03 +00:00
|
|
|
|
*pdwDataLen = (DWORD) cardid->size;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (cbData < cardid->size)
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
CopyMemory(pbData, cardid->blob, cardid->size);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(CP_CARD_SERIAL_NO, wszProperty) == 0) {
|
|
|
|
|
unsigned char buf[64];
|
|
|
|
|
size_t buf_len = sizeof(buf);
|
|
|
|
|
size_t sn_len = strlen(vs->p15card->tokeninfo->serial_number)/2;
|
|
|
|
|
|
|
|
|
|
if (sc_hex_to_bin(vs->p15card->tokeninfo->serial_number, buf, &buf_len)) {
|
2012-08-22 10:45:03 +00:00
|
|
|
|
buf_len = strlen(vs->p15card->tokeninfo->serial_number);
|
|
|
|
|
if (buf_len > SC_MAX_SERIALNR) {
|
|
|
|
|
buf_len = SC_MAX_SERIALNR;
|
|
|
|
|
}
|
|
|
|
|
memcpy(buf, vs->p15card->tokeninfo->serial_number, buf_len);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pdwDataLen)
|
2015-04-25 21:29:03 +00:00
|
|
|
|
*pdwDataLen = (DWORD) buf_len;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (cbData < buf_len)
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
CopyMemory(pbData, buf, buf_len);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2013-12-18 13:15:02 +00:00
|
|
|
|
else if (wcscmp(CP_CARD_PIN_INFO, wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
PPIN_INFO p = (PPIN_INFO) pbData;
|
2013-12-18 13:15:02 +00:00
|
|
|
|
|
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*p);
|
|
|
|
|
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
|
|
if (p->dwVersion != PIN_INFO_CURRENT_VERSION)
|
|
|
|
|
return ERROR_REVISION_MISMATCH;
|
|
|
|
|
|
2013-09-24 16:07:03 +00:00
|
|
|
|
p->PinType = vs->reader->capabilities & SC_READER_CAP_PIN_PAD ? ExternalPinType : AlphaNumericPinType;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
p->dwFlags = 0;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
switch (dwFlags) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
case ROLE_USER:
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 2,"returning info on PIN ROLE_USER ( Auth ) [%u]\n",dwFlags);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
p->PinPurpose = DigitalSignaturePin;
|
|
|
|
|
p->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
|
|
|
|
|
p->PinCachePolicy.dwPinCachePolicyInfo = 0;
|
|
|
|
|
p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
p->dwChangePermission = CREATE_PIN_SET(ROLE_USER);
|
|
|
|
|
p->dwUnblockPermission = CREATE_PIN_SET(ROLE_ADMIN);
|
|
|
|
|
break;
|
|
|
|
|
case ROLE_ADMIN:
|
|
|
|
|
logprintf(pCardData, 2,"returning info on PIN ROLE_ADMIN ( Unblock ) [%u]\n",dwFlags);
|
|
|
|
|
p->PinPurpose = UnblockOnlyPin;
|
|
|
|
|
p->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
|
|
|
|
|
p->PinCachePolicy.dwPinCachePolicyInfo = 0;
|
|
|
|
|
p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
|
|
|
|
|
p->dwChangePermission = CREATE_PIN_SET(ROLE_ADMIN);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
p->dwUnblockPermission = 0;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 0,"Invalid Pin number %u requested\n",dwFlags);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(CP_CARD_LIST_PINS,wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
PPIN_SET p = (PPIN_SET) pbData;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*p);
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
SET_PIN(*p, ROLE_USER);
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(CP_CARD_AUTHENTICATED_STATE,wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
PPIN_SET p = (PPIN_SET) pbData;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*p);
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 7, "CARD_AUTHENTICATED_STATE invalid\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else if (wcscmp(CP_CARD_PIN_STRENGTH_VERIFY,wszProperty) == 0) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD *p = (DWORD *)pbData;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (dwFlags != ROLE_USER)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*p);
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
*p = CARD_PIN_STRENGTH_PLAINTEXT;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2015-04-07 20:50:39 +00:00
|
|
|
|
else if (wcscmp(CP_KEY_IMPORT_SUPPORT, wszProperty) == 0) {
|
|
|
|
|
DWORD *p = (DWORD *)pbData;
|
|
|
|
|
if (pdwDataLen)
|
|
|
|
|
*pdwDataLen = sizeof(*p);
|
|
|
|
|
if (cbData < sizeof(*p))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
*p = 0;
|
|
|
|
|
}
|
2015-09-25 20:22:29 +00:00
|
|
|
|
else if (wcscmp(CP_ENUM_ALGORITHMS, wszProperty) == 0) {
|
|
|
|
|
logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty);
|
|
|
|
|
//TODO
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
else if (wcscmp(CP_PADDING_SCHEMES, wszProperty) == 0) {
|
|
|
|
|
logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty);
|
|
|
|
|
//TODO
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
else if (wcscmp(CP_CHAINING_MODES, wszProperty) == 0) {
|
|
|
|
|
logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty);
|
|
|
|
|
//TODO
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
else {
|
|
|
|
|
logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty);
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 7, "returns '%S' ", wszProperty);
|
|
|
|
|
loghex(pCardData, 7, pbData, *pdwDataLen);
|
|
|
|
|
return SCARD_S_SUCCESS;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPCWSTR wszProperty,
|
|
|
|
|
__in_bcount(cbDataLen) PBYTE pbData,
|
|
|
|
|
__in DWORD cbDataLen,
|
|
|
|
|
__in DWORD dwFlags)
|
|
|
|
|
{
|
2013-09-24 16:07:03 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardSetProperty\n");
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2013-09-24 16:07:03 +00:00
|
|
|
|
logprintf(pCardData, 2, "CardSetProperty wszProperty=%S, pbData=%p, cbDataLen=%u, dwFlags=%u",\
|
|
|
|
|
NULLWSTR(wszProperty),pbData,cbDataLen,dwFlags);
|
|
|
|
|
|
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!wszProperty)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-04-07 20:50:39 +00:00
|
|
|
|
if (dwFlags)
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-04-11 14:30:17 +00:00
|
|
|
|
if (!cbDataLen)
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-04-07 20:50:39 +00:00
|
|
|
|
/* the following properties cannot be set according to the minidriver specifications */
|
|
|
|
|
if (wcscmp(wszProperty,CP_CARD_FREE_SPACE) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_CARD_CAPABILITIES) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_CARD_KEYSIZES) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_CARD_LIST_PINS) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_CARD_AUTHENTICATED_STATE) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_KEY_IMPORT_SUPPORT) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_ENUM_ALGORITHMS) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_PADDING_SCHEMES) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_CHAINING_MODES) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_SUPPORTS_WIN_X509_ENROLLMENT) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_CARD_CACHE_MODE) == 0 ||
|
|
|
|
|
wcscmp(wszProperty,CP_CARD_SERIAL_NO) == 0
|
|
|
|
|
) {
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
2013-09-24 16:07:03 +00:00
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-04-07 20:50:39 +00:00
|
|
|
|
/* the following properties can be set, but are not implemented by the minidriver */
|
|
|
|
|
if (wcscmp(CP_CARD_PIN_STRENGTH_VERIFY, wszProperty) == 0 ||
|
|
|
|
|
wcscmp(CP_CARD_PIN_INFO, wszProperty) == 0 ||
|
|
|
|
|
wcscmp(CP_CARD_GUID, wszProperty) == 0 ) {
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-24 16:07:03 +00:00
|
|
|
|
/* This property and CP_PIN_CONTEXT_STRING are set just prior to a call to
|
|
|
|
|
* CardAuthenticateEx if the PIN required is declared of type ExternalPinType.
|
|
|
|
|
*/
|
2010-02-05 13:05:25 +00:00
|
|
|
|
if (wcscmp(CP_PARENT_WINDOW, wszProperty) == 0) {
|
2015-04-11 14:30:17 +00:00
|
|
|
|
if (cbDataLen != sizeof(HWND) || !pbData) {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
2010-02-05 13:05:25 +00:00
|
|
|
|
HWND cp = *((HWND *) pbData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (cp!=0 && !IsWindow(cp))
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2013-09-24 16:07:03 +00:00
|
|
|
|
vs->hwndParent = cp;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2015-04-17 19:39:41 +00:00
|
|
|
|
logprintf(pCardData, 3, "Saved parent window (%p)\n", vs->hwndParent);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
2015-04-07 20:50:39 +00:00
|
|
|
|
|
|
|
|
|
if (wcscmp(CP_PIN_CONTEXT_STRING, wszProperty) == 0) {
|
2015-04-17 19:39:41 +00:00
|
|
|
|
vs->wszPinContext = (PWSTR) pbData;
|
|
|
|
|
logprintf(pCardData, 3, "Saved PIN context string: %S\n", (PWSTR) pbData);
|
2015-04-07 20:50:39 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 3, "INVALID PARAMETER\n");
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-06 17:38:15 +00:00
|
|
|
|
|
|
|
|
|
// 4.8 Secure key injection
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** The CardImportSessionKey function imports a temporary session key to the card.
|
|
|
|
|
The session key is encrypted with a key exchange key, and the function returns a
|
|
|
|
|
handle of the imported session key to the caller.*/
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardImportSessionKey(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in BYTE bContainerIndex,
|
|
|
|
|
__in VOID *pPaddingInfo,
|
|
|
|
|
__in LPCWSTR pwszBlobType,
|
|
|
|
|
__in LPCWSTR pwszAlgId,
|
|
|
|
|
__out CARD_KEY_HANDLE *phKey,
|
|
|
|
|
__in_bcount(cbInput) PBYTE pbInput,
|
|
|
|
|
__in DWORD cbInput,
|
|
|
|
|
__in DWORD dwFlags
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(bContainerIndex);
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(pPaddingInfo);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszBlobType);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszAlgId);
|
|
|
|
|
UNREFERENCED_PARAMETER(phKey);
|
|
|
|
|
UNREFERENCED_PARAMETER(pbInput);
|
|
|
|
|
UNREFERENCED_PARAMETER(cbInput);
|
|
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardImportSessionKey - unsupported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** The MDImportSessionKey function imports a temporary session key to the card minidriver
|
|
|
|
|
and returns a key handle to the caller.*/
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI MDImportSessionKey(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPCWSTR pwszBlobType,
|
|
|
|
|
__in LPCWSTR pwszAlgId,
|
|
|
|
|
__out PCARD_KEY_HANDLE phKey,
|
|
|
|
|
__in_bcount(cbInput) PBYTE pbInput,
|
|
|
|
|
__in DWORD cbInput
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszBlobType);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszAlgId);
|
|
|
|
|
UNREFERENCED_PARAMETER(phKey);
|
|
|
|
|
UNREFERENCED_PARAMETER(pbInput);
|
|
|
|
|
UNREFERENCED_PARAMETER(cbInput);
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "MDImportSessionKey - unsupported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** The MDEncryptData function uses a key handle to encrypt data with a symmetric key.
|
|
|
|
|
The data is encrypted in a format that the smart card supports.*/
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI MDEncryptData(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in CARD_KEY_HANDLE hKey,
|
|
|
|
|
__in LPCWSTR pwszSecureFunction,
|
|
|
|
|
__in_bcount(cbInput) PBYTE pbInput,
|
|
|
|
|
__in DWORD cbInput,
|
|
|
|
|
__in DWORD dwFlags,
|
|
|
|
|
__deref_out_ecount(*pcEncryptedData)
|
|
|
|
|
PCARD_ENCRYPTED_DATA *ppEncryptedData,
|
|
|
|
|
__out PDWORD pcEncryptedData
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(hKey);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszSecureFunction);
|
|
|
|
|
UNREFERENCED_PARAMETER(pbInput);
|
|
|
|
|
UNREFERENCED_PARAMETER(cbInput);
|
|
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
|
UNREFERENCED_PARAMETER(ppEncryptedData);
|
|
|
|
|
UNREFERENCED_PARAMETER(pcEncryptedData);
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "MDEncryptData - unsupported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** The CardGetSharedKeyHandle function returns a session key handle to the caller.
|
|
|
|
|
Note: The manner in which this session key has been established is outside the
|
|
|
|
|
scope of this specification. For example, the session key could be established
|
|
|
|
|
by either a permanent shared key or a key derivation algorithm that has occurred
|
|
|
|
|
before the call to CardGetSharedKeyHandle.*/
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardGetSharedKeyHandle(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in_bcount(cbInput) PBYTE pbInput,
|
|
|
|
|
__in DWORD cbInput,
|
|
|
|
|
__deref_opt_out_bcount(*pcbOutput)
|
|
|
|
|
PBYTE *ppbOutput,
|
|
|
|
|
__out_opt PDWORD pcbOutput,
|
|
|
|
|
__out PCARD_KEY_HANDLE phKey
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(pbInput);
|
|
|
|
|
UNREFERENCED_PARAMETER(cbInput);
|
|
|
|
|
UNREFERENCED_PARAMETER(ppbOutput);
|
|
|
|
|
UNREFERENCED_PARAMETER(pcbOutput);
|
|
|
|
|
UNREFERENCED_PARAMETER(phKey);
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardGetSharedKeyHandle - unsupported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** The CardDestroyKey function releases a temporary key on the card. The card
|
|
|
|
|
should delete all of the key material that is associated with that key handle.*/
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardDestroyKey(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in CARD_KEY_HANDLE hKey
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(hKey);
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardDestroyKey - unsupported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** This function can be used to get properties for a cryptographic algorithm.*/
|
|
|
|
|
DWORD WINAPI CardGetAlgorithmProperty (
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in LPCWSTR pwszAlgId,
|
|
|
|
|
__in LPCWSTR pwszProperty,
|
|
|
|
|
__out_bcount_part_opt(cbData, *pdwDataLen)
|
|
|
|
|
PBYTE pbData,
|
|
|
|
|
__in DWORD cbData,
|
|
|
|
|
__out PDWORD pdwDataLen,
|
|
|
|
|
__in DWORD dwFlags
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszAlgId);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszProperty);
|
|
|
|
|
UNREFERENCED_PARAMETER(pbData);
|
|
|
|
|
UNREFERENCED_PARAMETER(cbData);
|
|
|
|
|
UNREFERENCED_PARAMETER(pdwDataLen);
|
|
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardGetAlgorithmProperty - unsupported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** This function is used to get the properties of a key.*/
|
|
|
|
|
DWORD WINAPI CardGetKeyProperty(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in CARD_KEY_HANDLE hKey,
|
|
|
|
|
__in LPCWSTR pwszProperty,
|
|
|
|
|
__out_bcount_part_opt(cbData, *pdwDataLen) PBYTE pbData,
|
|
|
|
|
__in DWORD cbData,
|
|
|
|
|
__out PDWORD pdwDataLen,
|
|
|
|
|
__in DWORD dwFlags
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(hKey);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszProperty);
|
|
|
|
|
UNREFERENCED_PARAMETER(pbData);
|
|
|
|
|
UNREFERENCED_PARAMETER(cbData);
|
|
|
|
|
UNREFERENCED_PARAMETER(pdwDataLen);
|
|
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardGetKeyProperty - unsupported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** This function is used to set the properties of a key.*/
|
|
|
|
|
DWORD WINAPI CardSetKeyProperty(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in CARD_KEY_HANDLE hKey,
|
|
|
|
|
__in LPCWSTR pwszProperty,
|
|
|
|
|
__in_bcount(cbInput) PBYTE pbInput,
|
|
|
|
|
__in DWORD cbInput,
|
|
|
|
|
__in DWORD dwFlags
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
|
UNREFERENCED_PARAMETER(hKey);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszProperty);
|
|
|
|
|
UNREFERENCED_PARAMETER(pbInput);
|
|
|
|
|
UNREFERENCED_PARAMETER(cbInput);
|
|
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardSetKeyProperty - unsupported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** CardProcessEncryptedData processes a set of encrypted data BLOBs by
|
|
|
|
|
sending them to the card where the data BLOBs are decrypted.*/
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardProcessEncryptedData(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in CARD_KEY_HANDLE hKey,
|
|
|
|
|
__in LPCWSTR pwszSecureFunction,
|
|
|
|
|
__in_ecount(cEncryptedData)
|
|
|
|
|
PCARD_ENCRYPTED_DATA pEncryptedData,
|
|
|
|
|
__in DWORD cEncryptedData,
|
|
|
|
|
__out_bcount_part_opt(cbOutput, *pdwOutputLen)
|
|
|
|
|
PBYTE pbOutput,
|
|
|
|
|
__in DWORD cbOutput,
|
|
|
|
|
__out_opt PDWORD pdwOutputLen,
|
|
|
|
|
__in DWORD dwFlags
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(pCardData);
|
|
|
|
|
UNREFERENCED_PARAMETER(hKey);
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszSecureFunction);
|
|
|
|
|
UNREFERENCED_PARAMETER(pEncryptedData);
|
|
|
|
|
UNREFERENCED_PARAMETER(cEncryptedData);
|
|
|
|
|
UNREFERENCED_PARAMETER(pbOutput);
|
|
|
|
|
UNREFERENCED_PARAMETER(cbOutput);
|
|
|
|
|
UNREFERENCED_PARAMETER(pdwOutputLen);
|
|
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
|
|
|
|
logprintf(pCardData, 1, "CardProcessEncryptedData - unsupported\n");
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** The CardCreateContainerEx function creates a new key container that the
|
|
|
|
|
container index identifies and the bContainerIndex parameter specifies. The function
|
|
|
|
|
associates the key container with the PIN that the PinId parameter specified.
|
|
|
|
|
This function is useful if the card-edge does not allow for changing the key attributes
|
|
|
|
|
after the key container is created. This function replaces the need to call
|
|
|
|
|
CardSetContainerProperty to set the CCP_PIN_IDENTIFIER property CardCreateContainer
|
|
|
|
|
is called.
|
|
|
|
|
The caller of this function can provide the key material that the card imports.
|
|
|
|
|
This is useful in those situations in which the card either does not support internal
|
|
|
|
|
key generation or the caller requests that the key be archived in the card.*/
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI CardCreateContainerEx(
|
|
|
|
|
__in PCARD_DATA pCardData,
|
|
|
|
|
__in BYTE bContainerIndex,
|
|
|
|
|
__in DWORD dwFlags,
|
|
|
|
|
__in DWORD dwKeySpec,
|
|
|
|
|
__in DWORD dwKeySize,
|
|
|
|
|
__in PBYTE pbKeyData,
|
|
|
|
|
__in PIN_ID PinId
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
if (PinId == ROLE_ADMIN)
|
|
|
|
|
return SCARD_W_SECURITY_VIOLATION;
|
|
|
|
|
if (PinId != ROLE_USER)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
/* basically CardCreateContainerEx is CardCreateContainer + the PinId */
|
|
|
|
|
return CardCreateContainer(pCardData, bContainerIndex, dwFlags, dwKeySpec, dwKeySize, pbKeyData);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
DWORD dwret, suppliedVersion = 0;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
|
|
|
|
if (!pCardData)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
if (dwFlags)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2015-04-06 17:38:15 +00:00
|
|
|
|
if (!(dwFlags & CARD_SECURE_KEY_INJECTION_NO_CARD_MODE)) {
|
|
|
|
|
if( pCardData->hSCardCtx == 0) {
|
|
|
|
|
logprintf(pCardData, 0, "Invalide handle.\n");
|
|
|
|
|
return SCARD_E_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
if( pCardData->hScard == 0) {
|
|
|
|
|
logprintf(pCardData, 0, "Invalide handle.\n");
|
|
|
|
|
return SCARD_E_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* secure key injection not supported */
|
|
|
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pCardData->pbAtr == NULL)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
if ( pCardData->pwszCardName == NULL )
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
/* <2 lenght or >=0x22 are not ISO compliant */
|
|
|
|
|
if (pCardData->cbAtr >= 0x22 || pCardData->cbAtr <= 0x2)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
/* ATR beginning by 0x00 or 0xFF are not ISO compliant */
|
|
|
|
|
if (pCardData->pbAtr[0] == 0xFF || pCardData->pbAtr[0] == 0x00)
|
|
|
|
|
return SCARD_E_UNKNOWN_CARD;
|
|
|
|
|
/* Memory management functions */
|
|
|
|
|
if ( ( pCardData->pfnCspAlloc == NULL ) ||
|
|
|
|
|
( pCardData->pfnCspReAlloc == NULL ) ||
|
|
|
|
|
( pCardData->pfnCspFree == NULL ) )
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-04-06 17:38:15 +00:00
|
|
|
|
/* The lowest supported version is 4 - maximum is 7. */
|
|
|
|
|
if (pCardData->dwVersion < MD_MINIMUM_VERSION_SUPPORTED)
|
|
|
|
|
return (DWORD) ERROR_REVISION_MISMATCH;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2015-04-06 17:38:15 +00:00
|
|
|
|
suppliedVersion = pCardData->dwVersion;
|
|
|
|
|
|
2010-06-11 07:35:45 +00:00
|
|
|
|
/* VENDOR SPECIFIC */
|
2012-05-31 14:40:36 +00:00
|
|
|
|
vs = pCardData->pvVendorSpecific = pCardData->pfnCspAlloc(sizeof(VENDOR_SPECIFIC));
|
2010-02-05 13:05:25 +00:00
|
|
|
|
memset(vs, 0, sizeof(VENDOR_SPECIFIC));
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "==================================================================\n");
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "CardAcquireContext, dwVersion=%u, name=%S,hScard=0x%08X, hSCardCtx=0x%08X\n",
|
|
|
|
|
pCardData->dwVersion, NULLWSTR(pCardData->pwszCardName),pCardData->hScard, pCardData->hSCardCtx);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
|
|
|
|
vs->hScard = pCardData->hScard;
|
|
|
|
|
vs->hSCardCtx = pCardData->hSCardCtx;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 2, "request version pCardData->dwVersion = %d\n", pCardData->dwVersion);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
pCardData->dwVersion = min(pCardData->dwVersion, MD_CURRENT_VERSION_SUPPORTED);
|
2010-02-17 07:51:52 +00:00
|
|
|
|
logprintf(pCardData, 2, "pCardData->dwVersion = %d\n", pCardData->dwVersion);
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = md_create_context(pCardData, vs);
|
2015-04-06 17:38:15 +00:00
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
pCardData->pfnCspFree(pCardData->pvVendorSpecific);
|
|
|
|
|
pCardData->pvVendorSpecific = NULL;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return dwret;
|
2015-04-06 17:38:15 +00:00
|
|
|
|
}
|
2012-05-31 14:40:36 +00:00
|
|
|
|
md_static_data.flags &= ~MD_STATIC_FLAG_CONTEXT_DELETED;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
pCardData->pfnCardDeleteContext = CardDeleteContext;
|
|
|
|
|
pCardData->pfnCardQueryCapabilities = CardQueryCapabilities;
|
|
|
|
|
pCardData->pfnCardDeleteContainer = CardDeleteContainer;
|
|
|
|
|
pCardData->pfnCardCreateContainer = CardCreateContainer;
|
|
|
|
|
pCardData->pfnCardGetContainerInfo = CardGetContainerInfo;
|
|
|
|
|
pCardData->pfnCardAuthenticatePin = CardAuthenticatePin;
|
|
|
|
|
pCardData->pfnCardGetChallenge = CardGetChallenge;
|
|
|
|
|
pCardData->pfnCardAuthenticateChallenge = CardAuthenticateChallenge;
|
|
|
|
|
pCardData->pfnCardUnblockPin = CardUnblockPin;
|
|
|
|
|
pCardData->pfnCardChangeAuthenticator = CardChangeAuthenticator;
|
2015-12-09 20:41:37 +00:00
|
|
|
|
pCardData->pfnCardDeauthenticate = CardDeauthenticate;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
pCardData->pfnCardCreateDirectory = CardCreateDirectory;
|
|
|
|
|
pCardData->pfnCardDeleteDirectory = CardDeleteDirectory;
|
|
|
|
|
pCardData->pvUnused3 = NULL;
|
|
|
|
|
pCardData->pvUnused4 = NULL;
|
|
|
|
|
pCardData->pfnCardCreateFile = CardCreateFile;
|
|
|
|
|
pCardData->pfnCardReadFile = CardReadFile;
|
|
|
|
|
pCardData->pfnCardWriteFile = CardWriteFile;
|
|
|
|
|
pCardData->pfnCardDeleteFile = CardDeleteFile;
|
|
|
|
|
pCardData->pfnCardEnumFiles = CardEnumFiles;
|
|
|
|
|
pCardData->pfnCardGetFileInfo = CardGetFileInfo;
|
|
|
|
|
pCardData->pfnCardQueryFreeSpace = CardQueryFreeSpace;
|
|
|
|
|
pCardData->pfnCardQueryKeySizes = CardQueryKeySizes;
|
|
|
|
|
pCardData->pfnCardSignData = CardSignData;
|
|
|
|
|
pCardData->pfnCardRSADecrypt = CardRSADecrypt;
|
|
|
|
|
pCardData->pfnCardConstructDHAgreement = CardConstructDHAgreement;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = associate_card(pCardData);
|
2015-04-06 17:38:15 +00:00
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
pCardData->pfnCspFree(pCardData->pvVendorSpecific);
|
|
|
|
|
pCardData->pvVendorSpecific = NULL;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return dwret;
|
2015-04-06 17:38:15 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dwret = md_fs_init(pCardData);
|
2015-04-06 17:38:15 +00:00
|
|
|
|
if (dwret != SCARD_S_SUCCESS) {
|
|
|
|
|
pCardData->pfnCspFree(pCardData->pvVendorSpecific);
|
|
|
|
|
pCardData->pvVendorSpecific = NULL;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
return dwret;
|
2015-04-06 17:38:15 +00:00
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 1, "OpenSC init done.\n");
|
2015-04-06 17:38:15 +00:00
|
|
|
|
logprintf(pCardData, 1, "Supplied version %u - version used %u.\n", suppliedVersion, pCardData->dwVersion);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2015-04-06 17:38:15 +00:00
|
|
|
|
if (pCardData->dwVersion >= CARD_DATA_VERSION_FIVE) {
|
2011-04-12 07:40:12 +00:00
|
|
|
|
pCardData->pfnCardDeriveKey = CardDeriveKey;
|
|
|
|
|
pCardData->pfnCardDestroyDHAgreement = CardDestroyDHAgreement;
|
|
|
|
|
|
2015-04-06 17:38:15 +00:00
|
|
|
|
if (pCardData->dwVersion >= CARD_DATA_VERSION_SIX) {
|
2013-12-19 08:34:52 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
pCardData->pfnCardGetChallengeEx = CardGetChallengeEx;
|
|
|
|
|
pCardData->pfnCardAuthenticateEx = CardAuthenticateEx;
|
|
|
|
|
pCardData->pfnCardChangeAuthenticatorEx = CardChangeAuthenticatorEx;
|
|
|
|
|
pCardData->pfnCardDeauthenticateEx = CardDeauthenticateEx;
|
|
|
|
|
pCardData->pfnCardGetContainerProperty = CardGetContainerProperty;
|
|
|
|
|
pCardData->pfnCardSetContainerProperty = CardSetContainerProperty;
|
|
|
|
|
pCardData->pfnCardGetProperty = CardGetProperty;
|
|
|
|
|
pCardData->pfnCardSetProperty = CardSetProperty;
|
2015-04-06 17:38:15 +00:00
|
|
|
|
if (pCardData->dwVersion >= CARD_DATA_VERSION_SEVEN) {
|
|
|
|
|
|
|
|
|
|
pCardData->pfnMDImportSessionKey = MDImportSessionKey;
|
|
|
|
|
pCardData->pfnMDEncryptData = MDEncryptData;
|
|
|
|
|
pCardData->pfnCardImportSessionKey = CardImportSessionKey;
|
|
|
|
|
pCardData->pfnCardGetSharedKeyHandle = CardGetSharedKeyHandle;
|
|
|
|
|
pCardData->pfnCardGetAlgorithmProperty = CardGetAlgorithmProperty;
|
|
|
|
|
pCardData->pfnCardGetKeyProperty = CardGetKeyProperty;
|
|
|
|
|
pCardData->pfnCardSetKeyProperty = CardSetKeyProperty;
|
|
|
|
|
pCardData->pfnCardProcessEncryptedData = CardProcessEncryptedData;
|
|
|
|
|
pCardData->pfnCardDestroyKey = CardDestroyKey;
|
|
|
|
|
pCardData->pfnCardCreateContainerEx = CardCreateContainerEx;
|
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2011-02-09 17:52:00 +00:00
|
|
|
|
}
|
2010-02-05 13:05:25 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int associate_card(PCARD_DATA pCardData)
|
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs;
|
|
|
|
|
DWORD dw;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
int r;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "associate_card\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
|
|
|
|
|
2011-04-12 07:40:12 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
2011-02-09 17:52:00 +00:00
|
|
|
|
/*
|
|
|
|
|
* set the addresses of the reader and card handles
|
2011-04-12 07:40:12 +00:00
|
|
|
|
* Our cardmod pcsc code will use these when we call sc_ctx_use_reader
|
2011-02-09 17:52:00 +00:00
|
|
|
|
* We use the address of the handles as provided in the pCardData
|
|
|
|
|
*/
|
|
|
|
|
vs->hSCardCtx = pCardData->hSCardCtx;
|
|
|
|
|
vs->hScard = pCardData->hScard;
|
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
/**
|
|
|
|
|
* Check if a linked context has been deleted - if so, repair shared data.
|
|
|
|
|
* Multithreaded issue - TODO: proper multithreaded handling
|
|
|
|
|
*/
|
|
|
|
|
if (md_static_data.flags & MD_STATIC_FLAG_CONTEXT_DELETED)
|
|
|
|
|
{
|
|
|
|
|
r = sc_context_repair(&(vs->ctx));
|
|
|
|
|
logprintf(pCardData, 2, "sc_context_repair called - result = %d, %s\n", r, sc_strerror(r));
|
|
|
|
|
md_static_data.flags &= ~MD_STATIC_FLAG_CONTEXT_DELETED;
|
|
|
|
|
}
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
|
|
|
|
/* set the provided reader and card handles into ctx */
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 5, "cardmod_use_handles %d\n", sc_ctx_use_reader(vs->ctx, &vs->hSCardCtx, &vs->hScard));
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
/* should be only one reader */
|
2012-05-31 14:40:36 +00:00
|
|
|
|
logprintf(pCardData, 5, "sc_ctx_get_reader_count(ctx): %d\n", sc_ctx_get_reader_count(vs->ctx));
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
|
|
|
|
vs->reader = sc_ctx_get_reader(vs->ctx, 0);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(vs->reader) {
|
|
|
|
|
struct sc_app_info *app_generic = NULL;
|
|
|
|
|
struct sc_aid *aid = NULL;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
r = sc_connect_card(vs->reader, &(vs->card));
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(r) {
|
|
|
|
|
logprintf(pCardData, 0, "Cannot connect card in reader '%s'\n", NULLSTR(vs->reader->name));
|
|
|
|
|
return SCARD_E_UNKNOWN_CARD;
|
|
|
|
|
}
|
|
|
|
|
logprintf(pCardData, 3, "Connected card in '%s'\n", NULLSTR(vs->reader->name));
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
app_generic = sc_pkcs15_get_application_by_type(vs->card, "generic");
|
|
|
|
|
if (app_generic)
|
|
|
|
|
logprintf(pCardData, 3, "Use generic application '%s'\n", app_generic->label);
|
|
|
|
|
aid = app_generic ? &app_generic->aid : NULL;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
r = sc_pkcs15_bind(vs->card, aid, &(vs->p15card));
|
|
|
|
|
logprintf(pCardData, 2, "PKCS#15 initialization result: %d, %s\n", r, sc_strerror(r));
|
2011-02-09 17:52:00 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(vs->card == NULL || vs->p15card == NULL) {
|
|
|
|
|
logprintf(pCardData, 0, "Card unknown.\n");
|
|
|
|
|
return SCARD_E_UNKNOWN_CARD;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dw = md_get_pin_by_role(pCardData, ROLE_USER, &vs->obj_user_pin);
|
|
|
|
|
if (dw != SCARD_S_SUCCESS) {
|
|
|
|
|
logprintf(pCardData, 2, "Cannot get User PIN object");
|
|
|
|
|
return dw;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
dw = md_get_pin_by_role(pCardData, ROLE_USER, &vs->obj_sopin);
|
|
|
|
|
if (dw != SCARD_S_SUCCESS)
|
|
|
|
|
logprintf(pCardData, 2, "Cannot get ADMIN PIN object -- ignored");
|
2011-03-23 18:37:46 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int disassociate_card(PCARD_DATA pCardData)
|
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
VENDOR_SPECIFIC *vs;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 1, "disassociate_card\n");
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if (!pCardData)
|
|
|
|
|
return SCARD_E_INVALID_PARAMETER;
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
|
2011-04-12 07:40:12 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
vs->obj_user_pin = NULL;
|
|
|
|
|
vs->obj_sopin = NULL;
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(vs->p15card) {
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 6, "sc_pkcs15_unbind\n");
|
|
|
|
|
sc_pkcs15_unbind(vs->p15card);
|
|
|
|
|
vs->p15card = NULL;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2012-05-31 14:40:36 +00:00
|
|
|
|
if(vs->card) {
|
2011-02-09 17:52:00 +00:00
|
|
|
|
logprintf(pCardData, 6, "sc_disconnect_card\n");
|
|
|
|
|
sc_disconnect_card(vs->card);
|
|
|
|
|
vs->card = NULL;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
vs->reader = NULL;
|
|
|
|
|
|
|
|
|
|
vs->hSCardCtx = -1;
|
|
|
|
|
vs->hScard = -1;
|
|
|
|
|
|
2010-02-05 13:05:25 +00:00
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-09 17:52:00 +00:00
|
|
|
|
|
2015-04-19 17:51:22 +00:00
|
|
|
|
BOOL APIENTRY DllMain( HINSTANCE hinstDLL,
|
2010-02-05 13:05:25 +00:00
|
|
|
|
DWORD ul_reason_for_call,
|
|
|
|
|
LPVOID lpReserved
|
|
|
|
|
)
|
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
CHAR name[MAX_PATH + 1] = "\0";
|
|
|
|
|
char *reason = "";
|
|
|
|
|
|
2015-03-28 12:04:41 +00:00
|
|
|
|
GetModuleFileNameA(GetModuleHandle(NULL),name,MAX_PATH);
|
2012-05-31 14:40:36 +00:00
|
|
|
|
|
|
|
|
|
switch (ul_reason_for_call) {
|
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
|
reason = "Attach Process";
|
|
|
|
|
break;
|
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
|
|
|
reason = "Attach Thread";
|
|
|
|
|
break;
|
|
|
|
|
case DLL_THREAD_DETACH:
|
|
|
|
|
reason = "Detach Thread";
|
|
|
|
|
break;
|
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
|
reason = "Detach Process";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 19:39:41 +00:00
|
|
|
|
logprintf(NULL,8,"\n********** DllMain Module(handle:0x%p) '%s'; reason='%s'; Reserved=%p; P:%d; T:%d\n",
|
2015-04-19 17:51:22 +00:00
|
|
|
|
hinstDLL, name, reason, lpReserved, GetCurrentProcessId(), GetCurrentThreadId());
|
2011-04-12 07:40:12 +00:00
|
|
|
|
switch (ul_reason_for_call)
|
2010-02-05 13:05:25 +00:00
|
|
|
|
{
|
2012-05-31 14:40:36 +00:00
|
|
|
|
case DLL_PROCESS_ATTACH:
|
2015-04-19 17:51:22 +00:00
|
|
|
|
g_inst = hinstDLL;
|
2012-05-31 14:40:36 +00:00
|
|
|
|
md_static_data.attach_check = MD_STATIC_PROCESS_ATTACHED;
|
|
|
|
|
break;
|
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
|
md_static_data.attach_check = 0;
|
|
|
|
|
break;
|
2010-02-05 13:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef _MANAGED
|
|
|
|
|
#pragma managed(pop)
|
|
|
|
|
#endif
|
2011-05-08 08:07:03 +00:00
|
|
|
|
#endif
|
|
|
|
|
|