2005-01-29 12:14:22 +00:00
|
|
|
|
/*
|
|
|
|
|
* card-belpic.c: Support for Belgium EID card
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2003, Zetes Belgium
|
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* About the Belpic (Belgian Personal Identity Card) card
|
|
|
|
|
*
|
2018-04-14 17:38:34 +00:00
|
|
|
|
* The Belpic card is a Cyberflex Java card, so you normally communicate
|
2005-01-29 12:14:22 +00:00
|
|
|
|
* with an applet running on the card. In order to support a pkcs15 file
|
|
|
|
|
* structure, an applet (the Belpic applet) has been build that emulates
|
|
|
|
|
* this. So the card's behaviour is specific for this Belpic applet, that's
|
|
|
|
|
* why a separate driver has been made.
|
|
|
|
|
*
|
|
|
|
|
* The card contains the citizen's ID data (name, address, photo, ...) and
|
2018-04-14 17:38:34 +00:00
|
|
|
|
* her keys and certs. The ID data are in a separate directory on the card and
|
2005-01-29 12:14:22 +00:00
|
|
|
|
* are not handled by this software. For the cryptographic data (keys and certs)
|
|
|
|
|
* a pkcs#15 structure has been chosen and they can be accessed and used
|
|
|
|
|
* by the OpenSC software.
|
|
|
|
|
*
|
|
|
|
|
* The current situation about the cryptographic data is: there is 1 PIN
|
|
|
|
|
* that protects 2 private keys and corresponding certs. Then there is a
|
|
|
|
|
* CA cert and the root cert. The first key (Auth Key) can be used for
|
2018-04-14 17:38:34 +00:00
|
|
|
|
* authentication, the second one (NonRep Key) for non repudiation purposes
|
2005-01-29 12:14:22 +00:00
|
|
|
|
* (so it can be used as an alternative to manual signatures).
|
|
|
|
|
*
|
|
|
|
|
* There are some special things to note, which all have some consequences:
|
|
|
|
|
* (1) the SELECT FILE command doesn't return any FCI (file length, type, ...)
|
|
|
|
|
* (2) the NonRep key needs a VERIFY PIN before a signature can be done with it
|
2018-04-14 17:38:34 +00:00
|
|
|
|
* (3) pin pad readers had to be supported by a proprietary interface (as at
|
|
|
|
|
* that moment no other solution was known/available/ready)
|
2005-01-29 12:14:22 +00:00
|
|
|
|
* The consequences are:
|
|
|
|
|
*
|
|
|
|
|
* For (1): we let the SELECT FILE command return that the file length is
|
2018-04-14 17:38:34 +00:00
|
|
|
|
* a fixed large number and that each file is a transparent working EF
|
2005-01-29 12:14:22 +00:00
|
|
|
|
* (except the root dir 3F 00). This way however, there is a problem with the
|
2018-04-14 17:38:34 +00:00
|
|
|
|
* sc_read_binary() function that will only stop reading until it receives
|
2005-01-29 12:14:22 +00:00
|
|
|
|
* a 0. Therefore, we use the 'next_idx' trick. Or, if that might fail
|
|
|
|
|
* and so a READ BINARY past the end of file is done, length 0 is returned
|
|
|
|
|
* instead of an error code.
|
|
|
|
|
*
|
|
|
|
|
* For (2), we decided that a GUI for asking the PIN would be the best
|
|
|
|
|
* thing to do (another option would be to make 2 virtual slots but that
|
|
|
|
|
* causes other problems and is less user-friendly). A GUI being popped up
|
|
|
|
|
* by the pkcs11 lib before each NonRep signature has another important
|
|
|
|
|
* security advantage: applications that cache the PIN can't silently do
|
2018-04-14 17:38:34 +00:00
|
|
|
|
* a NonRep signature because there will always be the GUI.
|
2005-01-29 12:14:22 +00:00
|
|
|
|
*
|
|
|
|
|
* For (3), we link dynamically against a pin pad lib (DLL) that implements the
|
2018-04-14 17:38:34 +00:00
|
|
|
|
* proprietary API for a specific pin pad. For each pin pad reader (identified
|
|
|
|
|
* by it's PC/SC reader name), a pin pad lib corresponds. Some reader/lib
|
2005-01-29 12:14:22 +00:00
|
|
|
|
* name pairs are hardcoded, and others can be added in the config file.
|
|
|
|
|
* Note that there's also a GUI used in this case: if a signature with the
|
|
|
|
|
* NonRep key is done: a dialog box is shown that asks the user to enter
|
|
|
|
|
* her PIN on the pin pad reader in order to make a legally valid signature.
|
|
|
|
|
*
|
|
|
|
|
* Further the (current) Belpic card as quite some limitations:
|
|
|
|
|
* no key pair generation or update of data except after establishing a Secure
|
|
|
|
|
* Channel or CTV-authentication (which can only be done at the municipalities),
|
|
|
|
|
* no encryption. The result is that only a very limited amount of functions
|
|
|
|
|
* is/had to be implemented to get the pkcs11 library working.
|
|
|
|
|
*
|
|
|
|
|
* About the belpic_set_language: the RA-PC software (including the pkcs11 lib)
|
|
|
|
|
* in the Brussels' communities should be able to change the language of the GUI
|
|
|
|
|
* messages. So the language set by this function takes priority on all other
|
|
|
|
|
* language-selection functionality.
|
|
|
|
|
*/
|
|
|
|
|
|
2015-04-22 21:55:33 +00:00
|
|
|
|
#if HAVE_CONFIG_H
|
2010-03-04 08:14:36 +00:00
|
|
|
|
#include "config.h"
|
2015-04-22 21:55:33 +00:00
|
|
|
|
#endif
|
2010-03-04 08:14:36 +00:00
|
|
|
|
|
2005-01-29 12:14:22 +00:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2010-03-04 08:14:36 +00:00
|
|
|
|
#include "internal.h"
|
|
|
|
|
#include "log.h"
|
|
|
|
|
|
2005-01-29 12:14:22 +00:00
|
|
|
|
/* To be removed */
|
|
|
|
|
#include <time.h>
|
|
|
|
|
static long t1, t2, tot_read = 0, tot_dur = 0, dur;
|
|
|
|
|
|
|
|
|
|
#define BELPIC_VERSION "1.4"
|
|
|
|
|
|
|
|
|
|
/* Most of the #defines here are also present in the pkcs15 files, but
|
|
|
|
|
* because this driver has no access to them, it's hardcoded here. If
|
|
|
|
|
* other Belpic cards with other 'settings' appear, we'll have to move
|
|
|
|
|
* these #defines to the struct belpic_priv_data */
|
2005-02-01 07:53:50 +00:00
|
|
|
|
#define BELPIC_MAX_FILE_SIZE 65535
|
2005-01-30 13:50:08 +00:00
|
|
|
|
#define BELPIC_PIN_BUF_SIZE 8
|
|
|
|
|
#define BELPIC_MIN_USER_PIN_LEN 4
|
|
|
|
|
#define BELPIC_MAX_USER_PIN_LEN 12
|
|
|
|
|
#define BELPIC_PIN_ENCODING SC_PIN_ENCODING_GLP
|
|
|
|
|
#define BELPIC_PAD_CHAR 0xFF
|
|
|
|
|
#define BELPIC_KEY_REF_NONREP 0x83
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
2015-03-26 12:16:04 +00:00
|
|
|
|
/* Data in the return value for the GET CARD DATA command:
|
|
|
|
|
* All fields are one byte, except when noted otherwise.
|
|
|
|
|
*
|
|
|
|
|
* See <EFBFBD>6.9 in
|
|
|
|
|
* https://github.com/Fedict/eid-mw/blob/master/doc/sdk/documentation/Public_Belpic_Applet_v1%207_Ref_Manual%20-%20A01.pdf
|
|
|
|
|
* for the full documentation on the GET CARD DATA command.
|
|
|
|
|
*/
|
|
|
|
|
// Card serial number (16 bytes)
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_SERIALNUM 0
|
|
|
|
|
// "Component code"
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_COMPCODE 16
|
|
|
|
|
// "OS number"
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_OSNUM 17
|
|
|
|
|
// "OS version"
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_OSVER 18
|
|
|
|
|
// "Softmask number"
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_SMNUM 19
|
|
|
|
|
// "Softmask version"
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_SMVER 20
|
|
|
|
|
// Applet version
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_APPLETVERS 21
|
|
|
|
|
// Global OS version (2 bytes)
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_GL_OSVE 22
|
|
|
|
|
// Applet interface version
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_APPINTVERS 24
|
|
|
|
|
// PKCS#1 support version
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_PKCS1 25
|
|
|
|
|
// Key exchange version
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_KEYX 26
|
|
|
|
|
// Applet life cycle (Should always be 0F for released cards, is 07 when not issued yet)
|
|
|
|
|
#define BELPIC_CARDDATA_OFF_APPLCYCLE 27
|
|
|
|
|
// Full length of reply
|
|
|
|
|
#define BELPIC_CARDDATA_RESP_LEN 28
|
|
|
|
|
|
2005-01-29 12:14:22 +00:00
|
|
|
|
/* Used for a trick in select file and read binary */
|
2005-08-03 18:29:21 +00:00
|
|
|
|
static size_t next_idx = (size_t)-1;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
2005-02-06 19:40:40 +00:00
|
|
|
|
static struct sc_atr_table belpic_atrs[] = {
|
2005-01-29 12:14:22 +00:00
|
|
|
|
/* Applet V1.1 */
|
2005-09-07 08:33:55 +00:00
|
|
|
|
{ "3B:98:13:40:0A:A5:03:01:01:01:AD:13:11", NULL, NULL, SC_CARD_TYPE_BELPIC_EID, 0, NULL },
|
2005-02-04 20:29:35 +00:00
|
|
|
|
/* Applet V1.0 with new EMV-compatible ATR */
|
2005-09-07 08:33:55 +00:00
|
|
|
|
{ "3B:98:94:40:0A:A5:03:01:01:01:AD:13:10", NULL, NULL, SC_CARD_TYPE_BELPIC_EID, 0, NULL },
|
2005-02-04 20:29:35 +00:00
|
|
|
|
/* Applet beta 5 + V1.0 */
|
2005-09-07 08:33:55 +00:00
|
|
|
|
{ "3B:98:94:40:FF:A5:03:01:01:01:AD:13:10", NULL, NULL, SC_CARD_TYPE_BELPIC_EID, 0, NULL },
|
|
|
|
|
{ NULL, NULL, NULL, 0, 0, NULL }
|
2005-01-29 12:14:22 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct sc_card_operations belpic_ops;
|
|
|
|
|
static struct sc_card_driver belpic_drv = {
|
2005-02-09 14:47:46 +00:00
|
|
|
|
"Belpic cards",
|
2005-01-29 12:14:22 +00:00
|
|
|
|
"belpic",
|
2005-09-07 08:33:55 +00:00
|
|
|
|
&belpic_ops,
|
|
|
|
|
NULL, 0, NULL
|
2005-01-29 12:14:22 +00:00
|
|
|
|
};
|
|
|
|
|
static const struct sc_card_operations *iso_ops = NULL;
|
|
|
|
|
|
2015-03-26 12:16:04 +00:00
|
|
|
|
static int get_carddata(sc_card_t *card, u8* carddata_loc, unsigned int carddataloc_len)
|
|
|
|
|
{
|
|
|
|
|
sc_apdu_t apdu;
|
|
|
|
|
u8 carddata_cmd[] = { 0x80, 0xE4, 0x00, 0x00, 0x1C };
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
|
|
assert(carddataloc_len == BELPIC_CARDDATA_RESP_LEN);
|
|
|
|
|
|
|
|
|
|
r = sc_bytes2apdu(card->ctx, carddata_cmd, sizeof(carddata_cmd), &apdu);
|
|
|
|
|
if(r) {
|
|
|
|
|
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "bytes to APDU conversion failed: %d\n", r);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
apdu.resp = carddata_loc;
|
|
|
|
|
apdu.resplen = carddataloc_len;
|
|
|
|
|
|
|
|
|
|
r = sc_transmit_apdu(card, &apdu);
|
|
|
|
|
if(r) {
|
|
|
|
|
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "GetCardData command failed: %d\n", r);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
|
|
|
|
if(r) {
|
|
|
|
|
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "GetCardData: card returned %d\n", r);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
if(apdu.resplen < carddataloc_len) {
|
2017-03-14 19:02:30 +00:00
|
|
|
|
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
|
"GetCardData: card returned %"SC_FORMAT_LEN_SIZE_T"u bytes rather than expected %d\n",
|
|
|
|
|
apdu.resplen, carddataloc_len);
|
2015-03-26 12:16:04 +00:00
|
|
|
|
return SC_ERROR_WRONG_LENGTH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-08 20:59:35 +00:00
|
|
|
|
static int belpic_match_card(sc_card_t *card)
|
2005-01-29 12:14:22 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
2005-02-06 19:40:40 +00:00
|
|
|
|
i = _sc_match_atr(card, belpic_atrs, &card->type);
|
2005-01-29 12:14:22 +00:00
|
|
|
|
if (i < 0)
|
|
|
|
|
return 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-08 20:59:35 +00:00
|
|
|
|
static int belpic_init(sc_card_t *card)
|
2005-01-29 12:14:22 +00:00
|
|
|
|
{
|
2015-03-26 12:16:04 +00:00
|
|
|
|
int key_size = 1024;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
int r;
|
2005-01-30 13:50:08 +00:00
|
|
|
|
|
2018-03-22 15:25:13 +00:00
|
|
|
|
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Belpic V%s\n", BELPIC_VERSION);
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
2005-02-06 19:40:40 +00:00
|
|
|
|
if (card->type < 0)
|
2005-02-10 10:07:13 +00:00
|
|
|
|
card->type = SC_CARD_TYPE_BELPIC_EID; /* Unknown card: assume it's the Belpic Card */
|
2005-02-06 19:40:40 +00:00
|
|
|
|
|
2005-01-29 12:14:22 +00:00
|
|
|
|
card->cla = 0x00;
|
2005-02-10 10:07:13 +00:00
|
|
|
|
if (card->type == SC_CARD_TYPE_BELPIC_EID) {
|
2017-10-31 09:18:35 +00:00
|
|
|
|
u8 carddata[BELPIC_CARDDATA_RESP_LEN];
|
|
|
|
|
memset(carddata, 0, sizeof(carddata));
|
|
|
|
|
|
2015-03-26 12:16:04 +00:00
|
|
|
|
if((r = get_carddata(card, carddata, sizeof(carddata))) < 0) {
|
|
|
|
|
return r;
|
|
|
|
|
}
|
2017-10-31 09:18:35 +00:00
|
|
|
|
if (carddata[BELPIC_CARDDATA_OFF_APPLETVERS] >= 0x17) {
|
2015-03-26 12:16:04 +00:00
|
|
|
|
key_size = 2048;
|
|
|
|
|
}
|
|
|
|
|
_sc_card_add_rsa_alg(card, key_size,
|
2017-10-31 09:18:35 +00:00
|
|
|
|
SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE, 0);
|
2005-01-29 12:14:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* State that we have an RNG */
|
|
|
|
|
card->caps |= SC_CARD_CAP_RNG;
|
|
|
|
|
|
|
|
|
|
card->max_pin_len = BELPIC_MAX_USER_PIN_LEN;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-08 20:59:35 +00:00
|
|
|
|
static int belpic_select_file(sc_card_t *card,
|
|
|
|
|
const sc_path_t *in_path, sc_file_t **file_out)
|
2005-01-29 12:14:22 +00:00
|
|
|
|
{
|
2005-03-08 20:59:35 +00:00
|
|
|
|
sc_apdu_t apdu;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
u8 pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
|
|
|
|
|
int r, pathlen;
|
2005-03-08 20:59:35 +00:00
|
|
|
|
sc_file_t *file = NULL;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
|
|
|
|
assert(card != NULL && in_path != NULL);
|
|
|
|
|
memcpy(path, in_path->value, in_path->len);
|
|
|
|
|
pathlen = in_path->len;
|
|
|
|
|
|
|
|
|
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x08, 0x0C);
|
2005-01-30 13:50:08 +00:00
|
|
|
|
|
2005-01-29 12:14:22 +00:00
|
|
|
|
apdu.lc = pathlen;
|
|
|
|
|
apdu.data = path;
|
|
|
|
|
apdu.datalen = pathlen;
|
|
|
|
|
|
|
|
|
|
apdu.resplen = 0;
|
|
|
|
|
apdu.le = 0;
|
|
|
|
|
|
|
|
|
|
r = sc_transmit_apdu(card, &apdu);
|
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Select File APDU transmit failed");
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
|
|
|
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
|
|
|
|
if (r)
|
2010-03-15 12:17:13 +00:00
|
|
|
|
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
2005-08-03 18:29:21 +00:00
|
|
|
|
next_idx = (size_t)-1; /* reset */
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
|
|
|
|
if (file_out != NULL) {
|
|
|
|
|
file = sc_file_new();
|
|
|
|
|
file->path = *in_path;
|
|
|
|
|
if (pathlen >= 2)
|
2005-01-30 13:50:08 +00:00
|
|
|
|
file->id = (in_path->value[pathlen - 2] << 8) | in_path->value[pathlen - 1];
|
2005-01-29 12:14:22 +00:00
|
|
|
|
file->size = BELPIC_MAX_FILE_SIZE;
|
|
|
|
|
file->shareable = 1;
|
|
|
|
|
file->ef_structure = SC_FILE_EF_TRANSPARENT;
|
|
|
|
|
if (pathlen == 2 && memcmp("\x3F\x00", in_path->value, 2) == 0)
|
2005-01-30 13:50:08 +00:00
|
|
|
|
file->type = SC_FILE_TYPE_DF;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
else
|
|
|
|
|
file->type = SC_FILE_TYPE_WORKING_EF;
|
|
|
|
|
*file_out = file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-08 20:59:35 +00:00
|
|
|
|
static int belpic_read_binary(sc_card_t *card,
|
2005-01-30 13:50:08 +00:00
|
|
|
|
unsigned int idx, u8 * buf, size_t count, unsigned long flags)
|
2005-01-29 12:14:22 +00:00
|
|
|
|
{
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
|
|
if (next_idx == idx)
|
2005-01-30 13:50:08 +00:00
|
|
|
|
return 0; /* File was already read entirely */
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
2005-01-30 13:50:08 +00:00
|
|
|
|
t1 = clock();
|
2005-01-29 12:14:22 +00:00
|
|
|
|
r = iso_ops->read_binary(card, idx, buf, count, flags);
|
2005-01-30 13:50:08 +00:00
|
|
|
|
t2 = clock();
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
|
|
|
|
/* If the 'next_idx trick' shouldn't work, we hope this error
|
|
|
|
|
* means that an attempt was made to read beyond the file's
|
|
|
|
|
* contents, so we'll return 0 to end the loop in sc_read_binary()*/
|
|
|
|
|
if (r == SC_ERROR_INCORRECT_PARAMETERS)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2005-08-02 21:13:06 +00:00
|
|
|
|
if (r >= 0 && (size_t)r < count)
|
|
|
|
|
next_idx = idx + (size_t)r;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
2005-01-30 13:50:08 +00:00
|
|
|
|
dur = t2 - t1;
|
|
|
|
|
tot_dur += dur;
|
|
|
|
|
tot_read += r;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-22 15:25:13 +00:00
|
|
|
|
static int belpic_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
|
2005-01-29 12:14:22 +00:00
|
|
|
|
{
|
|
|
|
|
data->pin1.encoding = data->pin2.encoding = BELPIC_PIN_ENCODING;
|
|
|
|
|
data->pin1.pad_char = data->pin2.pad_char = BELPIC_PAD_CHAR;
|
|
|
|
|
data->pin1.min_length = data->pin2.min_length = BELPIC_MIN_USER_PIN_LEN;
|
2010-08-12 21:49:14 +00:00
|
|
|
|
data->pin1.max_length = data->pin2.max_length = BELPIC_MAX_USER_PIN_LEN;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
data->apdu = NULL;
|
|
|
|
|
|
|
|
|
|
return iso_ops->pin_cmd(card, data, tries_left);
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-08 20:59:35 +00:00
|
|
|
|
static int belpic_set_security_env(sc_card_t *card,
|
|
|
|
|
const sc_security_env_t *env, int se_num)
|
2005-01-29 12:14:22 +00:00
|
|
|
|
{
|
2005-03-08 20:59:35 +00:00
|
|
|
|
sc_apdu_t apdu;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
|
|
|
|
int r;
|
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
|
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "belpic_set_security_env(), keyRef = 0x%0x, algo = 0x%0x\n",
|
2005-01-30 13:50:08 +00:00
|
|
|
|
*env->key_ref, env->algorithm_flags);
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
|
|
|
|
assert(card != NULL && env != NULL);
|
|
|
|
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
|
|
|
|
|
switch (env->operation) {
|
|
|
|
|
case SC_SEC_OPERATION_SIGN:
|
|
|
|
|
apdu.p1 = 0x41;
|
|
|
|
|
apdu.p2 = 0xB6;
|
2005-01-30 13:50:08 +00:00
|
|
|
|
sbuf[0] = 0x04; /* length of the following data */
|
|
|
|
|
sbuf[1] = 0x80; /* tag for algorithm reference */
|
2005-01-29 12:14:22 +00:00
|
|
|
|
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
|
|
|
|
sbuf[2] = 0x01;
|
|
|
|
|
else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
|
|
|
|
|
sbuf[2] = 0x02;
|
|
|
|
|
else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5)
|
|
|
|
|
sbuf[2] = 0x04;
|
|
|
|
|
else {
|
2010-03-15 12:17:13 +00:00
|
|
|
|
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Set Sec Env: unsupported algo 0X%0X\n",
|
2005-01-30 13:50:08 +00:00
|
|
|
|
env->algorithm_flags);
|
2005-01-29 12:14:22 +00:00
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
}
|
2005-01-30 13:50:08 +00:00
|
|
|
|
sbuf[3] = 0x84; /* tag for private key reference */
|
|
|
|
|
sbuf[4] = *env->key_ref; /* key reference */
|
2005-01-29 12:14:22 +00:00
|
|
|
|
apdu.lc = 5;
|
|
|
|
|
apdu.datalen = 5;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
apdu.le = 0;
|
|
|
|
|
apdu.data = sbuf;
|
|
|
|
|
apdu.resplen = 0;
|
|
|
|
|
|
|
|
|
|
r = sc_transmit_apdu(card, &apdu);
|
2010-03-15 12:17:13 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Set Security Env APDU transmit failed");
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
|
|
|
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
2010-03-15 12:17:13 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Card's Set Security Env command returned error");
|
2005-01-29 12:14:22 +00:00
|
|
|
|
|
|
|
|
|
/* If a NonRep signature will be done, ask to enter a PIN. It would be more
|
2005-01-30 13:50:08 +00:00
|
|
|
|
* logical to put the code below into the compute signature function because
|
2018-04-14 17:38:34 +00:00
|
|
|
|
* a Verify Pin call must immediately precede a Compute Signature call.
|
2005-01-30 13:50:08 +00:00
|
|
|
|
* It's not done because the Compute Signature is completely ISO7816 compliant
|
|
|
|
|
* so we use the iso7816_compute_signature() function, and because this function
|
|
|
|
|
* doesn't know about the key reference.
|
|
|
|
|
* It's not a problem either, because this function is (for pkcs11) only called
|
|
|
|
|
* by sc_pkcs15_compute_signature(), where the card is already locked, and
|
|
|
|
|
* the next function to be executed will be the compute_signature function.
|
|
|
|
|
*/
|
2005-01-29 12:14:22 +00:00
|
|
|
|
if (*env->key_ref == BELPIC_KEY_REF_NONREP) {
|
2010-03-15 12:17:13 +00:00
|
|
|
|
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "No GUI for NonRep key present, signature cancelled\n");
|
2005-08-18 14:01:54 +00:00
|
|
|
|
return SC_ERROR_NOT_SUPPORTED;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-30 13:50:08 +00:00
|
|
|
|
static struct sc_card_driver *sc_get_driver(void)
|
2005-01-29 12:14:22 +00:00
|
|
|
|
{
|
|
|
|
|
if (iso_ops == NULL)
|
|
|
|
|
iso_ops = sc_get_iso7816_driver()->ops;
|
|
|
|
|
|
|
|
|
|
belpic_ops.match_card = belpic_match_card;
|
|
|
|
|
belpic_ops.init = belpic_init;
|
|
|
|
|
|
2018-03-22 15:25:13 +00:00
|
|
|
|
belpic_ops.update_binary = iso_ops->update_binary;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
belpic_ops.select_file = belpic_select_file;
|
|
|
|
|
belpic_ops.read_binary = belpic_read_binary;
|
|
|
|
|
belpic_ops.pin_cmd = belpic_pin_cmd;
|
|
|
|
|
belpic_ops.set_security_env = belpic_set_security_env;
|
|
|
|
|
|
2018-03-22 15:25:13 +00:00
|
|
|
|
belpic_ops.compute_signature = iso_ops->compute_signature;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
belpic_ops.get_challenge = iso_ops->get_challenge;
|
|
|
|
|
belpic_ops.get_response = iso_ops->get_response;
|
|
|
|
|
belpic_ops.check_sw = iso_ops->check_sw;
|
|
|
|
|
|
2005-01-30 13:50:08 +00:00
|
|
|
|
return &belpic_drv;
|
2005-01-29 12:14:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 1
|
2005-01-30 13:50:08 +00:00
|
|
|
|
struct sc_card_driver *sc_get_belpic_driver(void)
|
2005-01-29 12:14:22 +00:00
|
|
|
|
{
|
|
|
|
|
return sc_get_driver();
|
|
|
|
|
}
|
|
|
|
|
#endif
|