2015-11-06 07:24:16 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2011 Frank Morgner
|
|
|
|
*
|
|
|
|
* This file is part of OpenSC.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* This example shows how to use the library functions perform_pace to
|
|
|
|
* get a secure channel to the nPA. We use the builtin function npa_change_pin
|
|
|
|
* to modify the PIN using the secure channel. Then we transmit an arbitrary
|
|
|
|
* APDU encrypted and authenticated to the card using sm_transmit_apdu. */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_OPENPACE
|
|
|
|
#include "libopensc/sm.h"
|
|
|
|
#include "sm/sm-iso.h"
|
|
|
|
#include "sm/sm-eac.h"
|
2018-01-25 22:30:51 +00:00
|
|
|
#include "libopensc/card-npa.h"
|
2015-11-06 07:24:16 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
static const char *newpin = NULL;
|
|
|
|
static const char *pin = NULL;
|
|
|
|
|
|
|
|
/* SELECT the Master File (MF) */
|
|
|
|
const unsigned char apdubuf[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0x3F, 0x00};
|
|
|
|
|
|
|
|
int
|
|
|
|
main (int argc, char **argv)
|
|
|
|
{
|
|
|
|
/* Set up the environment */
|
|
|
|
int r;
|
|
|
|
|
|
|
|
sc_context_t *ctx = NULL;
|
|
|
|
sc_card_t *card = NULL;
|
|
|
|
sc_reader_t *reader = NULL;
|
|
|
|
|
|
|
|
sc_apdu_t apdu;
|
|
|
|
u8 buf[0xffff];
|
|
|
|
|
|
|
|
struct establish_pace_channel_input pace_input;
|
|
|
|
struct establish_pace_channel_output pace_output;
|
|
|
|
|
|
|
|
memset(&pace_input, 0, sizeof pace_input);
|
|
|
|
memset(&pace_output, 0, sizeof pace_output);
|
|
|
|
|
|
|
|
|
|
|
|
/* Connect to a reader */
|
|
|
|
r = sc_establish_context(&ctx, "example");
|
|
|
|
if (r < 0 || !ctx) {
|
|
|
|
fprintf(stderr, "Failed to create initial context: %s", sc_strerror(r));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
reader = sc_ctx_get_reader(ctx, 0);
|
|
|
|
if (!reader) {
|
|
|
|
fprintf(stderr, "Failed to access reader 0");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Connect to a nPA */
|
|
|
|
ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER;
|
|
|
|
if (sc_connect_card(reader, &card) < 0) {
|
|
|
|
fprintf(stderr, "Could not connect to card\n");
|
|
|
|
sc_release_context(ctx);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize OpenPACE */
|
|
|
|
EAC_init();
|
|
|
|
|
|
|
|
|
|
|
|
/* Now we try to change the PIN. Therefor we need to establish a SM channel
|
|
|
|
* with PACE.
|
|
|
|
*
|
|
|
|
* You could set your PIN with pin=“123456”; or just leave it at NULL to be
|
|
|
|
* asked for it. The same applies to the new PIN newpin. */
|
|
|
|
pace_input.pin_id = PACE_PIN;
|
|
|
|
pace_input.pin = (unsigned char *) pin;
|
|
|
|
pace_input.pin_length = pin ? strlen(pin) : 0;
|
|
|
|
|
|
|
|
r = perform_pace(card, pace_input, &pace_output, EAC_TR_VERSION_2_02);
|
|
|
|
if (r < 0)
|
|
|
|
goto err;
|
|
|
|
printf("Established PACE channel with PIN.\n");
|
|
|
|
|
|
|
|
r = npa_change_pin(card, newpin, newpin ? strlen(newpin) : 0);
|
|
|
|
if (r < 0)
|
|
|
|
goto err;
|
|
|
|
printf("Changed PIN.\n");
|
|
|
|
|
|
|
|
|
|
|
|
/* Now we want to transmit additional APDUs in the established SM channel.
|
|
|
|
*
|
|
|
|
* Here we are parsing the raw apdu buffer apdubuf to be transformed into
|
|
|
|
* an sc_apdu_t. Alternatively you could also set CLA, INS, P1, P2, ... by
|
|
|
|
* hand in the sc_apdu_t object. */
|
|
|
|
r = sc_bytes2apdu(ctx, apdubuf, sizeof apdubuf, &apdu);
|
|
|
|
if (r < 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* write the response data to buf */
|
|
|
|
apdu.resp = buf;
|
|
|
|
apdu.resplen = sizeof buf;
|
|
|
|
|
|
|
|
/* Transmit the APDU with SM */
|
|
|
|
r = sc_transmit_apdu(card, &apdu);
|
|
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
fprintf(r < 0 ? stderr : stdout, "%s\n", sc_strerror(r));
|
|
|
|
|
|
|
|
/* Free up memory and wipe it if necessary (e.g. for keys stored in sm_ctx) */
|
|
|
|
free(pace_output.ef_cardaccess);
|
|
|
|
free(pace_output.recent_car);
|
|
|
|
free(pace_output.previous_car);
|
|
|
|
free(pace_output.id_icc);
|
|
|
|
free(pace_output.id_pcd);
|
|
|
|
|
|
|
|
sc_sm_stop(card);
|
|
|
|
sc_reset(card, 1);
|
|
|
|
sc_disconnect_card(card);
|
|
|
|
sc_release_context(ctx);
|
|
|
|
EAC_cleanup();
|
|
|
|
|
|
|
|
return -r;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
int
|
|
|
|
main (int argc, char **argv)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|