diff --git a/npa/Makefile.am b/npa/Makefile.am
index 871599e..6628066 100644
--- a/npa/Makefile.am
+++ b/npa/Makefile.am
@@ -1,7 +1,7 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src m4 doc win32
-EXTRA_DIST = libnpa.pc.in apdus test_vicc_with_npa.sh
+EXTRA_DIST = libnpa.pc.in apdus test_vicc_with_npa-tool.sh
do_subst = $(SED) \
-e 's,[@]PACKAGE_NAME[@],$(PACKAGE_NAME),g' \
diff --git a/npa/configure.ac b/npa/configure.ac
index ada0638..817038e 100644
--- a/npa/configure.ac
+++ b/npa/configure.ac
@@ -55,9 +55,9 @@ test -z "$OPENSC_LIBS" && OPENSC_LIBS="-lopensc"
saved_LIBS="$LIBS"
LIBS="$LDFLAGS $OPENSC_LIBS"
-AC_MSG_CHECKING([for sc_perform_pace])
-AC_TRY_LINK_FUNC(sc_perform_pace, [ AC_MSG_RESULT([yes]) ],
- [ AC_MSG_ERROR([libopensc with PACE (git clone git://github.com/frankmorgner/OpenSC.git) not found, use ./configure OPENSC_LIBS=...]) ])
+AC_MSG_CHECKING([for iasecc_sm_external_authentication])
+AC_TRY_LINK_FUNC(iasecc_sm_external_authentication, [ AC_MSG_RESULT([yes]) ],
+ [ AC_MSG_ERROR([libopensc configured with SM (git clone git://github.com/frankmorgner/OpenSC.git) not found, use ./configure OPENSC_LIBS=...]) ])
LIBS="$saved_LIBS"
diff --git a/npa/src/Makefile.am b/npa/src/Makefile.am
index c8de471..5cc968d 100644
--- a/npa/src/Makefile.am
+++ b/npa/src/Makefile.am
@@ -14,9 +14,9 @@ MAINTAINERCLEANFILES = $(BUILT_SOURCES) npa-tool.ggo $(dist_man1_MANS)
dist_man1_MANS = npa-tool.1
-AM_CPPFLAGS = -I$(top_srcdir)/src/npa -I$(top_srcdir)/src/opensc/src
+AM_CPPFLAGS = -I$(top_srcdir)/src/opensc/src -DENABLE_SM
-libnpa_la_SOURCES = sm.c scutil.c npa.c sslutil.c
+libnpa_la_SOURCES = iso-sm.c scutil.c npa.c
libnpa_la_LIBADD = $(OPENSSL_LIBS) $(OPENPACE_LIBS) $(OPENSC_LIBS)
libnpa_la_CFLAGS = $(OPENSSL_CFLAGS) $(OPENPACE_CFLAGS)
libnpa_la_LDFLAGS = -no-undefined
@@ -56,6 +56,6 @@ noinst_HEADERS = \
sslutil.h
nobase_include_HEADERS = \
- npa/sm.h \
+ npa/iso-sm.h \
npa/npa.h \
npa/scutil.h
diff --git a/npa/src/example.c b/npa/src/example.c
index 7560e24..8b39a4d 100644
--- a/npa/src/example.c
+++ b/npa/src/example.c
@@ -17,10 +17,14 @@
* npa. If not, see .
*/
-/* This example shows how to use the library functions EstablishPACEChannel to
+/* 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
+
#include
#include
#include
@@ -46,11 +50,9 @@ main (int argc, char **argv)
sc_apdu_t apdu;
u8 buf[0xffff];
- struct sm_ctx sctx;
struct establish_pace_channel_input pace_input;
struct establish_pace_channel_output pace_output;
- memset(&sctx, 0, sizeof sctx);
memset(&pace_input, 0, sizeof pace_input);
memset(&pace_output, 0, sizeof pace_output);
@@ -78,13 +80,12 @@ main (int argc, char **argv)
pace_input.pin = (unsigned char *) pin;
pace_input.pin_length = pin ? strlen(pin) : 0;
- r = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
- &sctx, EAC_TR_VERSION_2_02);
+ 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(&sctx, card, newpin, newpin ? strlen(newpin) : 0);
+ r = npa_change_pin(card, newpin, newpin ? strlen(newpin) : 0);
if (r < 0)
goto err;
printf("Changed PIN.\n");
@@ -104,14 +105,13 @@ main (int argc, char **argv)
apdu.resplen = sizeof buf;
/* Transmit the APDU with SM */
- r = sm_transmit_apdu(&sctx, card, &apdu);
+ 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) */
- sm_ctx_clear_free(&sctx);
if (pace_output.ef_cardaccess)
free(pace_output.ef_cardaccess);
if (pace_output.recent_car)
@@ -123,6 +123,7 @@ err:
if (pace_output.id_pcd)
free(pace_output.id_pcd);
+ sm_stop(card);
sc_reset(card, 1);
sc_disconnect_card(card);
sc_release_context(ctx);
diff --git a/npa/src/sm.c b/npa/src/iso-sm.c
similarity index 74%
rename from npa/src/sm.c
rename to npa/src/iso-sm.c
index a7947c9..4f30130 100644
--- a/npa/src/sm.c
+++ b/npa/src/iso-sm.c
@@ -16,13 +16,68 @@
* You should have received a copy of the GNU General Public License along with
* ccid. If not, see .
*/
-#include "scutil.h"
-#include "sm.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include
#include
+#include
+#include
#include
#include
+/* @brief Protect an APDU with Secure Messaging
+ *
+ * If secure messaging (SM) is activated in \a sctx and \a apdu is not already
+ * SM protected, \a apdu is processed with the following steps:
+ * \li call to \a sctx->pre_transmit
+ * \li encrypt \a apdu calling \a sctx->encrypt
+ * \li authenticate \a apdu calling \a sctx->authenticate
+ * \li copy the SM protected data to \a sm_apdu
+ *
+ * Data for authentication or encryption is always padded before the callback
+ * functions are called
+ *
+ * @param[in] card
+ * @param[in] apdu
+ * @param[in,out] sm_apdu
+ *
+ * @return \c SC_SUCCESS or error code if an error occurred
+ */
+static int iso_get_sm_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu);
+
+/* @brief Remove Secure Messaging from an APDU
+ *
+ * If secure messaging (SM) is activated in \a sctx and \a apdu is not already
+ * SM protected, \a apdu is processed with the following steps:
+ * \li verify SM protected \a apdu calling \a sctx->verify_authentication
+ * \li decrypt SM protected \a apdu calling \a sctx->decrypt
+ * \li copy decrypted/authenticated data and status bytes to \a apdu
+ *
+ * Callback functions must not remove padding.
+ *
+ * @param[in] card
+ * @param[in,out] apdu
+ * @param[in,out] sm_apdu will be freed when done.
+ *
+ * @return \c SC_SUCCESS or error code if an error occurred
+ */
+static int iso_free_sm_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu);
+
+/**
+ * @brief Cleans up allocated ressources of the ISO SM driver
+ *
+ * \c iso_sm_close() is designed as SM card operation. However, have in mind
+ * that this card operation is not called automatically for \c
+ * sc_disconnect_card() .
+ *
+ * @param[in] card
+ *
+ * @return \c SC_SUCCESS or error code if an error occurred
+ */
+static int iso_sm_close(struct sc_card *card);
+
static const struct sc_asn1_entry c_sm_capdu[] = {
{ "Padding-content indicator followed by cryptogram",
SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x07, SC_ASN1_OPTIONAL, NULL, NULL },
@@ -73,7 +128,7 @@ add_iso_pad(const u8 *data, size_t datalen, int block_size, u8 **padded)
}
static int
-add_padding(const struct sm_ctx *ctx, const u8 *data, size_t datalen,
+add_padding(const struct iso_sm_ctx *ctx, const u8 *data, size_t datalen,
u8 **padded)
{
u8 *p;
@@ -97,7 +152,7 @@ add_padding(const struct sm_ctx *ctx, const u8 *data, size_t datalen,
}
static int
-no_padding(u8 padding_indicator, const u8 *data, size_t datalen)
+rm_padding(u8 padding_indicator, const u8 *data, size_t datalen)
{
if (!datalen || !data)
return SC_ERROR_INVALID_ARGUMENTS;
@@ -108,6 +163,7 @@ no_padding(u8 padding_indicator, const u8 *data, size_t datalen)
case SM_NO_PADDING:
len = datalen;
break;
+
case SM_ISO_PADDING:
len = datalen;
@@ -121,6 +177,7 @@ no_padding(u8 padding_indicator, const u8 *data, size_t datalen)
return SC_ERROR_INVALID_DATA;
break;
+
default:
return SC_ERROR_NOT_SUPPORTED;
}
@@ -184,7 +241,7 @@ static int prefix_buf(u8 prefix, u8 *buf, size_t buflen, u8 **cat)
return buflen + 1;
}
-static int format_data(sc_card_t *card, const struct sm_ctx *ctx,
+static int format_data(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *data, size_t datalen,
struct sc_asn1_entry *formatted_encrypted_data_entry,
u8 **formatted_data, size_t *formatted_data_len)
@@ -236,7 +293,7 @@ err:
return r;
}
-static int format_head(const struct sm_ctx *ctx, const sc_apdu_t *apdu,
+static int format_head(const struct iso_sm_ctx *ctx, const sc_apdu_t *apdu,
u8 **formatted_head)
{
if (!apdu || !formatted_head)
@@ -255,16 +312,17 @@ static int format_head(const struct sm_ctx *ctx, const sc_apdu_t *apdu,
return add_padding(ctx, *formatted_head, 4, formatted_head);
}
-static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
- const sc_apdu_t *apdu, sc_apdu_t *sm_apdu)
+static int sm_encrypt(const struct iso_sm_ctx *ctx, sc_card_t *card,
+ const sc_apdu_t *apdu, sc_apdu_t **psm_apdu)
{
struct sc_asn1_entry sm_capdu[4];
u8 *p, *le = NULL, *sm_data = NULL, *fdata = NULL, *mac_data = NULL,
- *asn1 = NULL, *mac = NULL;
+ *asn1 = NULL, *mac = NULL, *resp_data = NULL;
size_t sm_data_len, fdata_len, mac_data_len, asn1_len, mac_len, le_len;
int r;
+ sc_apdu_t *sm_apdu = NULL;
- if (!apdu || !ctx || !card || !card->reader || !sm_apdu) {
+ if (!apdu || !ctx || !card || !card->reader || !psm_apdu) {
r = SC_ERROR_INVALID_ARGUMENTS;
goto err;
}
@@ -277,6 +335,11 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
sc_copy_asn1_entry(c_sm_capdu, sm_capdu);
+ sm_apdu = malloc(sizeof(sc_apdu_t));
+ if (!sm_apdu) {
+ r = SC_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
sm_apdu->control = apdu->control;
sm_apdu->flags = apdu->flags;
sm_apdu->cla = apdu->cla|0x0C;
@@ -426,40 +489,51 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
r = sc_asn1_encode(card->ctx, sm_capdu, (u8 **) &sm_data, &sm_data_len);
if (r < 0)
goto err;
- if (sm_apdu->datalen < sm_data_len) {
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Data for SM APDU too long");
+ sm_apdu->data = sm_data;
+ sm_apdu->datalen = sm_data_len;
+ sm_apdu->lc = sm_data_len;
+ sm_apdu->le = 0;
+ if (apdu->cse & SC_APDU_EXT) {
+ sm_apdu->cse = SC_APDU_CASE_4_EXT;
+#if OPENSC_NOT_BOGUS_ANYMORE
+ sm_apdu->resplen = 0xffff+1;
+#else
+ sm_apdu->resplen = SC_MAX_EXT_APDU_BUFFER_SIZE;
+#endif
+ } else {
+ sm_apdu->cse = SC_APDU_CASE_4_SHORT;
+#if OPENSC_NOT_BOGUS_ANYMORE
+ sm_apdu->resplen = 0xff+1;
+#else
+ sm_apdu->resplen = SC_MAX_APDU_BUFFER_SIZE;
+#endif
+ }
+ resp_data = malloc(sm_apdu->resplen);
+ if (!resp_data) {
r = SC_ERROR_OUT_OF_MEMORY;
goto err;
}
- /* Flawfinder: ignore */
- memcpy((u8 *) sm_apdu->data, sm_data, sm_data_len);
- sm_apdu->datalen = sm_data_len;
- sm_apdu->lc = sm_apdu->datalen;
- sm_apdu->le = 0;
- if (apdu->cse & SC_APDU_EXT)
- sm_apdu->cse = SC_APDU_CASE_4_EXT;
- else
- sm_apdu->cse = SC_APDU_CASE_4_SHORT;
+ sm_apdu->resp = resp_data;
bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ASN.1 encoded encrypted APDU data", sm_apdu->data, sm_apdu->datalen);
+ *psm_apdu = sm_apdu;
+
err:
- if (fdata)
- free(fdata);
- if (asn1)
- free(asn1);
- if (mac_data)
- free(mac_data);
- if (mac)
- free(mac);
- if (le)
- free(le);
- if (sm_data)
+ free(fdata);
+ free(asn1);
+ free(mac_data);
+ free(mac);
+ free(le);
+ if (r < 0) {
+ free(resp_data);
+ free(sm_apdu);
free(sm_data);
+ }
return r;
}
-static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
+static int sm_decrypt(const struct iso_sm_ctx *ctx, sc_card_t *card,
const sc_apdu_t *sm_apdu, sc_apdu_t *apdu)
{
int r;
@@ -520,7 +594,7 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
goto err;
buf_len = r;
- r = no_padding(ctx->padding_indicator, data, buf_len);
+ r = rm_padding(ctx->padding_indicator, data, buf_len);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not remove padding");
goto err;
@@ -572,42 +646,35 @@ err:
return r;
}
-int sm_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card,
- sc_apdu_t *apdu)
+static int iso_add_sm(struct iso_sm_ctx *sctx, sc_card_t *card,
+ sc_apdu_t *apdu, sc_apdu_t **sm_apdu)
{
- sc_apdu_t sm_apdu;
- u8 rbuf[0xffff], sbuf[0xffff];
-
- if (!card)
+ if (!card || !sctx)
return SC_ERROR_INVALID_ARGUMENTS;
- sm_apdu.data = sbuf;
- sm_apdu.datalen = sizeof sbuf;
- sm_apdu.resp = rbuf;
- sm_apdu.resplen = sizeof rbuf;
-
- if (!sctx || !sctx->active) {
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Secure messaging disabled.");
- return sc_transmit_apdu(card, apdu);
- }
-
if ((apdu->cla & 0x0C) == 0x0C) {
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Given APDU is already protected with some secure messaging. Deactivating own SM context.");
- sctx->active = 0;
- return sc_transmit_apdu(card, apdu);
+ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Given APDU is already protected with some secure messaging. Closing own SM context.");
+ SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, iso_sm_close(card),
+ "Could not close ISO SM session");
+ return SC_ERROR_SM_NOT_APPLIED;
}
if (sctx->pre_transmit)
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sctx->pre_transmit(card, sctx, apdu),
"Could not complete SM specific pre transmit routine");
- SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sm_encrypt(sctx, card, apdu, &sm_apdu),
+ SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sm_encrypt(sctx, card, apdu, sm_apdu),
"Could not encrypt APDU");
- SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sc_transmit_apdu(card, &sm_apdu),
- "Could not transmit SM APDU");
+
+ return SC_SUCCESS;
+}
+
+static int iso_rm_sm(struct iso_sm_ctx *sctx, sc_card_t *card,
+ sc_apdu_t *sm_apdu, sc_apdu_t *apdu)
+{
if (sctx->post_transmit)
- SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sctx->post_transmit(card, sctx, &sm_apdu),
+ SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sctx->post_transmit(card, sctx, sm_apdu),
"Could not complete SM specific post transmit routine");
- SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sm_decrypt(sctx, card, &sm_apdu, apdu),
+ SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sm_decrypt(sctx, card, sm_apdu, apdu),
"Could not decrypt APDU");
if (sctx->finish)
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sctx->finish(card, sctx, apdu),
@@ -616,8 +683,92 @@ int sm_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card,
return SC_SUCCESS;
}
-void sm_ctx_clear_free(const struct sm_ctx *sctx)
+int iso_sm_close(struct sc_card *card)
+{
+ if (card) {
+ iso_sm_ctx_clear_free(card->sm_ctx.info.cmd_data);
+ card->sm_ctx.info.cmd_data = NULL;
+ }
+
+ return SC_SUCCESS;
+}
+
+int iso_get_sm_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu)
+{
+ return iso_add_sm(card->sm_ctx.info.cmd_data, card, apdu, sm_apdu);
+}
+
+int iso_free_sm_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu)
+{
+ if (!sm_apdu)
+ return SC_ERROR_INVALID_ARGUMENTS;
+
+ struct sc_apdu *p = *sm_apdu;
+
+ int r = iso_rm_sm(card->sm_ctx.info.cmd_data, card, p, apdu);
+
+ if (p) {
+ free((unsigned char *) p->data);
+ free((unsigned char *) p->resp);
+ }
+ free(*sm_apdu);
+ *sm_apdu = NULL;
+
+ return r;
+}
+
+struct iso_sm_ctx *iso_sm_ctx_create(void)
+{
+ struct iso_sm_ctx *sctx = malloc(sizeof *sctx);
+ if (!sctx)
+ return NULL;
+
+ sctx->priv_data = NULL;
+ sctx->padding_indicator = SM_ISO_PADDING;
+ sctx->block_length = 0;
+ sctx->authenticate = NULL;
+ sctx->verify_authentication = NULL;
+ sctx->encrypt = NULL;
+ sctx->decrypt = NULL;
+ sctx->pre_transmit = NULL;
+ sctx->post_transmit = NULL;
+ sctx->finish = NULL;
+ sctx->clear_free = NULL;
+
+ return sctx;
+}
+
+void iso_sm_ctx_clear_free(struct iso_sm_ctx *sctx)
{
if (sctx && sctx->clear_free)
sctx->clear_free(sctx);
+ free(sctx);
+}
+
+int iso_sm_start(struct sc_card *card, struct iso_sm_ctx *sctx)
+{
+ if (!card)
+ return SC_ERROR_INVALID_ARGUMENTS;
+
+ if (card->sm_ctx.ops.close)
+ card->sm_ctx.ops.close(card);
+
+ card->sm_ctx.info.cmd_data = sctx;
+ card->sm_ctx.ops.close = iso_sm_close;
+ card->sm_ctx.ops.free_sm_apdu = iso_free_sm_apdu;
+ card->sm_ctx.ops.get_sm_apdu = iso_get_sm_apdu;
+ card->sm_ctx.sm_mode = SM_MODE_TRANSMIT;
+}
+
+int sm_stop(struct sc_card *card)
+{
+ int r = SC_SUCCESS;
+
+ if (card) {
+ if (card->sm_ctx.ops.close)
+ r = card->sm_ctx.ops.close(card);
+ card->sm_ctx.sm_mode = SM_MODE_NONE;
+ }
+
+ return r;
}
diff --git a/npa/src/npa-tool.c b/npa/src/npa-tool.c
index 2d68ad6..c421a09 100644
--- a/npa/src/npa-tool.c
+++ b/npa/src/npa-tool.c
@@ -16,6 +16,10 @@
* You should have received a copy of the GNU General Public License along with
* npa. If not, see .
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "cmdline.h"
#include "config.h"
#include
@@ -103,7 +107,7 @@ err:
return r;
}
-int npa_translate_apdus(struct sm_ctx *sctx, sc_card_t *card, FILE *input)
+int npa_translate_apdus(sc_card_t *card, FILE *input)
{
u8 buf[4 + 3 + 0xffff + 3];
char *read = NULL;
@@ -150,7 +154,7 @@ int npa_translate_apdus(struct sm_ctx *sctx, sc_card_t *card, FILE *input)
apdu.resp = buf;
apdu.resplen = sizeof buf;
- r = sm_transmit_apdu(sctx, card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Could not send C-APDU: %s", sc_strerror(r));
@@ -173,7 +177,6 @@ main (int argc, char **argv)
{
int r, oindex = 0, tr_version = EAC_TR_VERSION_2_02;
size_t channeldatalen;
- struct sm_ctx sctx, tmpctx;
struct establish_pace_channel_input pace_input;
struct establish_pace_channel_output pace_output;
struct timeval tv;
@@ -184,8 +187,6 @@ main (int argc, char **argv)
struct gengetopt_args_info cmdline;
- memset(&sctx, 0, sizeof sctx);
- memset(&tmpctx, 0, sizeof tmpctx);
memset(&pace_input, 0, sizeof pace_input);
memset(&pace_output, 0, sizeof pace_output);
@@ -319,8 +320,7 @@ main (int argc, char **argv)
(unsigned int) tv.tv_sec, (unsigned int) tv.tv_usec,
npa_secret_name(pace_input.pin_id), pace_input.pin);
- r = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
- &sctx, tr_version);
+ r = perform_pace(card, pace_input, &pace_output, tr_version);
secret++;
} while (0 > r && secret <= maxsecret);
@@ -348,8 +348,7 @@ main (int argc, char **argv)
pace_input.pin = NULL;
pace_input.pin_length = 0;
}
- r = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
- &tmpctx, tr_version);
+ r = perform_pace(card, pace_input, &pace_output, tr_version);
if (r < 0)
goto err;
printf("Established PACE channel with CAN.\n");
@@ -362,8 +361,7 @@ main (int argc, char **argv)
pace_input.pin = NULL;
pace_input.pin_length = 0;
}
- r = EstablishPACEChannel(&tmpctx, card, pace_input, &pace_output,
- &sctx, tr_version);
+ r = perform_pace(card, pace_input, &pace_output, tr_version);
if (r < 0)
goto err;
printf("Established PACE channel with PIN. PIN resumed.\n");
@@ -378,13 +376,12 @@ main (int argc, char **argv)
pace_input.pin = NULL;
pace_input.pin_length = 0;
}
- r = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
- &sctx, tr_version);
+ r = perform_pace(card, pace_input, &pace_output, tr_version);
if (r < 0)
goto err;
printf("Established PACE channel with PUK.\n");
- r = npa_unblock_pin(&sctx, card);
+ r = npa_unblock_pin(card);
if (r < 0)
goto err;
printf("Unblocked PIN.\n");
@@ -399,13 +396,12 @@ main (int argc, char **argv)
pace_input.pin = NULL;
pace_input.pin_length = 0;
}
- r = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
- &sctx, tr_version);
+ r = perform_pace(card, pace_input, &pace_output, tr_version);
if (r < 0)
goto err;
printf("Established PACE channel with PIN.\n");
- r = npa_change_pin(&sctx, card, newpin, newpin ? strlen(newpin) : 0);
+ r = npa_change_pin(card, newpin, newpin ? strlen(newpin) : 0);
if (r < 0)
goto err;
printf("Changed PIN.\n");
@@ -499,21 +495,20 @@ main (int argc, char **argv)
exit(1);
}
- r = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
- &sctx, tr_version);
+ r = perform_pace(card, pace_input, &pace_output, tr_version);
if (r < 0)
goto err;
printf("Established PACE channel with %s.\n",
npa_secret_name(pace_input.pin_id));
if (cmdline.cv_certificate_given || cmdline.private_key_given) {
- r = perform_terminal_authentication(&sctx, card, certs, certs_lens,
+ r = perform_terminal_authentication(card, certs, certs_lens,
privkey, privkey_len, auxiliary_data, auxiliary_data_len);
if (r < 0)
goto err;
printf("Performed Terminal Authentication.\n");
- r = perform_chip_authentication(&sctx, card);
+ r = perform_chip_authentication(card);
if (r < 0)
goto err;
printf("Performed Chip Authentication.\n");
@@ -530,7 +525,7 @@ main (int argc, char **argv)
}
}
- r = npa_translate_apdus(&sctx, card, input);
+ r = npa_translate_apdus(card, input);
if (r < 0)
goto err;
fclose(input);
@@ -540,8 +535,6 @@ main (int argc, char **argv)
err:
cmdline_parser_free(&cmdline);
- sm_ctx_clear_free(&sctx);
- sm_ctx_clear_free(&tmpctx);
if (pace_output.ef_cardaccess)
free(pace_output.ef_cardaccess);
if (pace_output.recent_car)
@@ -567,6 +560,7 @@ err:
if (cvc_cert)
CVC_CERT_free(cvc_cert);
+ sm_stop(card);
sc_reset(card, 1);
sc_disconnect_card(card);
sc_release_context(ctx);
diff --git a/npa/src/npa.c b/npa/src/npa.c
index 73f06e6..4ce566a 100644
--- a/npa/src/npa.c
+++ b/npa/src/npa.c
@@ -16,18 +16,22 @@
* You should have received a copy of the GNU General Public License along with
* ccid. If not, see .
*/
-#include "npa.h"
-#include "scutil.h"
-#include "sm.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "sslutil.h"
+#include
#include
#include
#include
-#include
#include
#include
#include
#include
+#include
+#include
+#include
#include
#include
#include
@@ -235,22 +239,22 @@ extern BUF_MEM *BUF_MEM_create(size_t len);
extern BUF_MEM *BUF_MEM_create_init(const void *buf, size_t len);
-static int npa_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx,
+static int npa_sm_encrypt(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *data, size_t datalen, u8 **enc);
-static int npa_sm_decrypt(sc_card_t *card, const struct sm_ctx *ctx,
+static int npa_sm_decrypt(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *enc, size_t enclen, u8 **data);
-static int npa_sm_authenticate(sc_card_t *card, const struct sm_ctx *ctx,
+static int npa_sm_authenticate(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *data, size_t datalen, u8 **outdata);
-static int npa_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
+static int npa_sm_verify_authentication(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *mac, size_t maclen,
const u8 *macdata, size_t macdatalen);
-static int npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
+static int npa_sm_pre_transmit(sc_card_t *card, const struct iso_sm_ctx *ctx,
sc_apdu_t *apdu);
-static int npa_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx,
+static int npa_sm_post_transmit(sc_card_t *card, const struct iso_sm_ctx *ctx,
sc_apdu_t *sm_apdu);
-static int npa_sm_finish(sc_card_t *card, const struct sm_ctx *ctx,
+static int npa_sm_finish(sc_card_t *card, const struct iso_sm_ctx *ctx,
sc_apdu_t *apdu);
-static void npa_sm_clear_free(const struct sm_ctx *ctx);
+static void npa_sm_clear_free(const struct iso_sm_ctx *ctx);
char npa_default_flags = 0;
@@ -295,7 +299,7 @@ err:
}
-int GetReadersPACECapabilities(u8 *bitmap)
+int get_pace_capabilities(u8 *bitmap)
{
if (!bitmap)
return SC_ERROR_INVALID_ARGUMENTS;
@@ -311,7 +315,7 @@ int GetReadersPACECapabilities(u8 *bitmap)
/** Read an EF.
* @note MF must be selected before calling this function.
* */
-static int get_ef(struct sm_ctx *npactx, sc_card_t *card, unsigned char sfid,
+static int get_ef(sc_card_t *card, unsigned char sfid,
u8 **ef, size_t *ef_len)
{
int r;
@@ -322,6 +326,7 @@ static int get_ef(struct sm_ctx *npactx, sc_card_t *card, unsigned char sfid,
sc_apdu_t apdu;
sc_file_t *file = NULL;
u8 *p;
+ struct iso_sm_ctx *iso_sm_ctx = card->sm_ctx.info.cmd_data;
if (!card || !ef || !ef_len) {
r = SC_ERROR_INVALID_ARGUMENTS;
@@ -330,12 +335,14 @@ static int get_ef(struct sm_ctx *npactx, sc_card_t *card, unsigned char sfid,
*ef_len = 0;
if (read > SC_MAX_APDU_BUFFER_SIZE-2
- || (npactx && read > (((SC_MAX_APDU_BUFFER_SIZE-2
+ || (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT
+ && read > (((SC_MAX_APDU_BUFFER_SIZE-2
/* for encrypted APDUs we usually get authenticated status
* bytes (4B), a MAC (11B) and a cryptogram with padding
* indicator (3B without data). The cryptogram is always
* padded to the block size. */
- -18) / npactx->block_length) * npactx->block_length - 1)))
+ -18) / iso_sm_ctx->block_length)
+ * iso_sm_ctx->block_length - 1)))
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_EXT,
ISO_READ_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
else
@@ -352,10 +359,7 @@ static int get_ef(struct sm_ctx *npactx, sc_card_t *card, unsigned char sfid,
apdu.resplen = read;
apdu.le = read;
- if (!npactx)
- r = sc_transmit_apdu(card, &apdu);
- else
- r = sm_transmit_apdu(npactx, card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
/* emulate the behaviour of sc_read_binary */
if (r >= 0)
r = apdu.resplen;
@@ -378,22 +382,8 @@ static int get_ef(struct sm_ctx *npactx, sc_card_t *card, unsigned char sfid,
}
*ef = p;
- if (!npactx)
- r = sc_read_binary(card, *ef_len,
- *ef + *ef_len, read, 0);
- else {
- if (*ef_len > 0x7fff) {
- r = SC_ERROR_OFFSET_TOO_LARGE;
- goto err;
- }
- apdu.p1 = (*ef_len >> 8) & 0x7F;
- apdu.p2 = *ef_len & 0xFF;
- apdu.resp = *ef + *ef_len;
- r = sm_transmit_apdu(npactx, card, &apdu);
- /* emulate the behaviour of sc_read_binary */
- if (r >= 0)
- r = apdu.resplen;
- }
+ r = sc_read_binary(card, *ef_len,
+ *ef + *ef_len, read, 0);
}
/* test cards only return an empty FCI template,
@@ -413,10 +403,10 @@ err:
return r;
}
-int get_ef_card_access(struct sm_ctx *oldnpactx, sc_card_t *card,
+int get_ef_card_access(sc_card_t *card,
u8 **ef_cardaccess, size_t *length_ef_cardaccess)
{
- return get_ef(oldnpactx, card, SFID_EF_CARDACCESS, ef_cardaccess, length_ef_cardaccess);
+ return get_ef(card, SFID_EF_CARDACCESS, ef_cardaccess, length_ef_cardaccess);
}
static int format_mse_cdata(struct sc_context *ctx, int protocol,
@@ -532,7 +522,7 @@ err:
}
#define ISO_MSE 0x22
-static int npa_mse(struct sm_ctx *oldnpactx, sc_card_t *card,
+static int npa_mse(sc_card_t *card,
unsigned char p1, unsigned char p2, int protocol,
const unsigned char *key_reference1, size_t key_reference1_len,
const unsigned char *key_reference2, size_t key_reference2_len,
@@ -562,10 +552,7 @@ static int npa_mse(struct sm_ctx *oldnpactx, sc_card_t *card,
apdu.lc = r;
- if (oldnpactx)
- r = sm_transmit_apdu(oldnpactx, card, &apdu);
- else
- r = sc_transmit_apdu(card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0)
goto err;
@@ -587,28 +574,26 @@ err:
return r;
}
-static int npa_mse_set_at(struct sm_ctx *oldnpactx, sc_card_t *card,
- unsigned char p1, int protocol,
+static int npa_mse_set_at(sc_card_t *card, unsigned char p1, int protocol,
const unsigned char *key_reference1, size_t key_reference1_len,
const unsigned char *key_reference2, size_t key_reference2_len,
const unsigned char *eph_pub_key, size_t eph_pub_key_len,
const unsigned char *auxiliary_data, size_t auxiliary_data_len,
const CVC_CHAT *chat, u8 *sw1, u8 *sw2)
{
- return npa_mse(oldnpactx, card, p1, 0xa4, protocol, key_reference1,
+ return npa_mse(card, p1, 0xa4, protocol, key_reference1,
key_reference1_len, key_reference2, key_reference2_len,
eph_pub_key, eph_pub_key_len, auxiliary_data, auxiliary_data_len,
chat, sw1, sw2);
}
-static int npa_mse_set_at_pace(struct sm_ctx *oldnpactx, sc_card_t *card,
- int protocol, enum s_type secret_key, const CVC_CHAT *chat, u8 *sw1,
- u8 *sw2)
+static int npa_mse_set_at_pace(sc_card_t *card, int protocol,
+ enum s_type secret_key, const CVC_CHAT *chat, u8 *sw1, u8 *sw2)
{
int r, tries;
char key = secret_key;
- r = npa_mse_set_at(oldnpactx, card, 0xC1, protocol, &key, sizeof key, NULL,
+ r = npa_mse_set_at(card, 0xC1, protocol, &key, sizeof key, NULL,
0, NULL, 0, NULL, 0, chat, sw1, sw2);
if (*sw1 == 0x63) {
@@ -639,8 +624,8 @@ static int npa_mse_set_at_pace(struct sm_ctx *oldnpactx, sc_card_t *card,
#define ISO_GENERAL_AUTHENTICATE 0x86
#define ISO_COMMAND_CHAINING 0x10
-static int npa_gen_auth_1_encrypted_nonce(struct sm_ctx *oldnpactx,
- sc_card_t *card, u8 **enc_nonce, size_t *enc_nonce_len)
+static int npa_gen_auth_1_encrypted_nonce(sc_card_t *card,
+ u8 **enc_nonce, size_t *enc_nonce_len)
{
sc_apdu_t apdu;
NPA_GEN_AUTH_PACE_C *c_data = NULL;
@@ -672,10 +657,7 @@ static int npa_gen_auth_1_encrypted_nonce(struct sm_ctx *oldnpactx,
apdu.resplen = sizeof resp;
apdu.resp = resp;
- if (oldnpactx)
- r = sm_transmit_apdu(oldnpactx, card, &apdu);
- else
- r = sc_transmit_apdu(card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0)
goto err;
@@ -725,9 +707,9 @@ err:
return r;
}
-static int npa_gen_auth_2_map_nonce(struct sm_ctx *oldnpactx,
- sc_card_t *card, const u8 *in, size_t in_len, u8 **map_data_out,
- size_t *map_data_out_len)
+static int npa_gen_auth_2_map_nonce(sc_card_t *card,
+ const u8 *in, size_t in_len,
+ u8 **map_data_out, size_t *map_data_out_len)
{
sc_apdu_t apdu;
NPA_GEN_AUTH_PACE_C *c_data = NULL;
@@ -767,10 +749,7 @@ static int npa_gen_auth_2_map_nonce(struct sm_ctx *oldnpactx,
apdu.resplen = sizeof resp;
apdu.resp = resp;
- if (oldnpactx)
- r = sm_transmit_apdu(oldnpactx, card, &apdu);
- else
- r = sc_transmit_apdu(card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0)
goto err;
@@ -820,9 +799,9 @@ err:
return r;
}
-static int npa_gen_auth_3_perform_key_agreement(
- struct sm_ctx *oldnpactx, sc_card_t *card,
- const u8 *in, size_t in_len, u8 **eph_pub_key_out, size_t *eph_pub_key_out_len)
+static int npa_gen_auth_3_perform_key_agreement(sc_card_t *card,
+ const u8 *in, size_t in_len,
+ u8 **eph_pub_key_out, size_t *eph_pub_key_out_len)
{
sc_apdu_t apdu;
NPA_GEN_AUTH_PACE_C *c_data = NULL;
@@ -862,10 +841,7 @@ static int npa_gen_auth_3_perform_key_agreement(
apdu.resplen = sizeof resp;
apdu.resp = resp;
- if (oldnpactx)
- r = sm_transmit_apdu(oldnpactx, card, &apdu);
- else
- r = sc_transmit_apdu(card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0)
goto err;
@@ -915,10 +891,10 @@ err:
return r;
}
-static int npa_gen_auth_4_mutual_authentication(
- struct sm_ctx *oldnpactx, sc_card_t *card,
- const u8 *in, size_t in_len, u8 **auth_token_out,
- size_t *auth_token_out_len, u8 **recent_car, size_t *recent_car_len,
+static int npa_gen_auth_4_mutual_authentication(sc_card_t *card,
+ const u8 *in, size_t in_len,
+ u8 **auth_token_out, size_t *auth_token_out_len,
+ u8 **recent_car, size_t *recent_car_len,
u8 **prev_car, size_t *prev_car_len)
{
sc_apdu_t apdu;
@@ -958,10 +934,7 @@ static int npa_gen_auth_4_mutual_authentication(
apdu.resplen = sizeof resp;
apdu.resp = resp;
- if (oldnpactx)
- r = sm_transmit_apdu(oldnpactx, card, &apdu);
- else
- r = sc_transmit_apdu(card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0)
goto err;
@@ -1037,9 +1010,8 @@ err:
}
int
-npa_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
- enum s_type pin_id, int ask_for_secret,
- const char *new, size_t new_len)
+npa_reset_retry_counter(sc_card_t *card, enum s_type pin_id,
+ int ask_for_secret, const char *new, size_t new_len)
{
sc_apdu_t apdu;
char *p = NULL;
@@ -1079,7 +1051,7 @@ npa_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
apdu.cse = SC_APDU_CASE_1;
}
- r = sm_transmit_apdu(ctx, card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (p) {
OPENSSL_cleanse(p, new_len);
@@ -1133,10 +1105,10 @@ get_psec(sc_card_t *card, const char *pin, size_t length_pin, enum s_type pin_id
return r;
}
-int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
+static int establish_pace_channel(sc_card_t *card,
struct establish_pace_channel_input pace_input,
struct establish_pace_channel_output *pace_output,
- struct sm_ctx *sctx, enum eac_tr_version tr_version)
+ struct iso_sm_ctx *sctx, enum eac_tr_version tr_version)
{
u8 *p = NULL;
EAC_CTX *eac_ctx = NULL;
@@ -1245,7 +1217,7 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
r = card->reader->ops->perform_pace(card->reader, &pace_input, pace_output);
} else {
if (!pace_output->ef_cardaccess_length || !pace_output->ef_cardaccess) {
- r = get_ef_card_access(oldnpactx, card, &pace_output->ef_cardaccess,
+ r = get_ef_card_access(card, &pace_output->ef_cardaccess,
&pace_output->ef_cardaccess_length);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardAccess.");
@@ -1274,7 +1246,7 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
eac_ctx->tr_version = tr_version;
- r = npa_mse_set_at_pace(oldnpactx, card, eac_ctx->pace_ctx->protocol,
+ r = npa_mse_set_at_pace(card, eac_ctx->pace_ctx->protocol,
pace_input.pin_id, chat, &pace_output->mse_set_at_sw1,
&pace_output->mse_set_at_sw2);
if (r < 0) {
@@ -1289,7 +1261,7 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
r = SC_ERROR_OUT_OF_MEMORY;
goto err;
}
- r = npa_gen_auth_1_encrypted_nonce(oldnpactx, card, (u8 **) &enc_nonce->data,
+ r = npa_gen_auth_1_encrypted_nonce(card, (u8 **) &enc_nonce->data,
&enc_nonce->length);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get encrypted nonce from card "
@@ -1323,7 +1295,7 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
r = SC_ERROR_INTERNAL;
goto err;
}
- r = npa_gen_auth_2_map_nonce(oldnpactx, card, (u8 *) mdata->data, mdata->length,
+ r = npa_gen_auth_2_map_nonce(card, (u8 *) mdata->data, mdata->length,
(u8 **) &mdata_opp->data, &mdata_opp->length);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange mapping data with card "
@@ -1349,7 +1321,7 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
r = SC_ERROR_INTERNAL;
goto err;
}
- r = npa_gen_auth_3_perform_key_agreement(oldnpactx, card, (u8 *) pub->data, pub->length,
+ r = npa_gen_auth_3_perform_key_agreement(card, (u8 *) pub->data, pub->length,
(u8 **) &pub_opp->data, &pub_opp->length);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange ephemeral public key with card "
@@ -1376,7 +1348,7 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
r = SC_ERROR_INTERNAL;
goto err;
}
- r = npa_gen_auth_4_mutual_authentication(oldnpactx, card, (u8 *) token->data, token->length,
+ r = npa_gen_auth_4_mutual_authentication(card, (u8 *) token->data, token->length,
(u8 **) &token_opp->data, &token_opp->length,
&pace_output->recent_car, &pace_output->recent_car_length,
&pace_output->previous_car, &pace_output->previous_car_length);
@@ -1456,7 +1428,6 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
sctx->clear_free = npa_sm_clear_free;
sctx->padding_indicator = SM_ISO_PADDING;
sctx->block_length = EVP_CIPHER_block_size(eac_ctx->key_ctx->cipher);
- sctx->active = 1;
}
err:
@@ -1495,24 +1466,47 @@ err:
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
}
-static int npa_mse_set_at_ta(struct sm_ctx *npactx, sc_card_t *card,
- int protocol, const unsigned char *chr, size_t chr_len,
+int perform_pace(sc_card_t *card,
+ struct establish_pace_channel_input pace_input,
+ struct establish_pace_channel_output *pace_output,
+ enum eac_tr_version tr_version)
+{
+ int r;
+ struct iso_sm_ctx *sctx = iso_sm_ctx_create();
+
+ if (!sctx)
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
+ SC_ERROR_OUT_OF_MEMORY);
+
+ r = establish_pace_channel(card, pace_input, pace_output, sctx, tr_version);
+
+ if (r < 0) {
+ iso_sm_ctx_clear_free(sctx);
+ } else {
+ iso_sm_start(card, sctx);
+ }
+
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
+}
+
+static int npa_mse_set_at_ta(sc_card_t *card, int protocol,
+ const unsigned char *chr, size_t chr_len,
const unsigned char *eph_pub_key, size_t eph_pub_key_len,
const unsigned char *auxiliary_data, size_t auxiliary_data_len)
{
- return npa_mse_set_at(npactx, card, 0x81, protocol, chr, chr_len, NULL, 0,
+ return npa_mse_set_at(card, 0x81, protocol, chr, chr_len, NULL, 0,
eph_pub_key, eph_pub_key_len, auxiliary_data, auxiliary_data_len,
NULL, NULL, NULL);
}
-static int npa_mse_set_dst(struct sm_ctx *npactx, sc_card_t *card,
+static int npa_mse_set_dst(sc_card_t *card,
const unsigned char *chr, size_t chr_len)
{
- return npa_mse(npactx, card, 0x81, 0xb6, 0, chr, chr_len, NULL, 0, NULL, 0,
- NULL, 0, NULL, NULL, NULL);
+ return npa_mse(card, 0x81, 0xb6, 0, chr, chr_len, NULL, 0, NULL, 0, NULL,
+ 0, NULL, NULL, NULL);
}
-static int npa_get_challenge(struct sm_ctx *npactx, sc_card_t *card,
+static int npa_get_challenge(sc_card_t *card,
unsigned char *challenge, size_t len)
{
sc_apdu_t apdu;
@@ -1532,10 +1526,7 @@ static int npa_get_challenge(struct sm_ctx *npactx, sc_card_t *card,
apdu.resplen = len;
apdu.resp = challenge;
- if (npactx)
- r = sm_transmit_apdu(npactx, card, &apdu);
- else
- r = sc_transmit_apdu(card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0)
goto err;
@@ -1545,7 +1536,7 @@ err:
return r;
}
-static int npa_verify(struct sm_ctx *npactx, sc_card_t *card,
+static int npa_verify(sc_card_t *card,
const unsigned char *cert, size_t cert_len)
{
sc_apdu_t apdu;
@@ -1575,10 +1566,7 @@ static int npa_verify(struct sm_ctx *npactx, sc_card_t *card,
apdu.datalen = length;
apdu.lc = length;
- if (npactx)
- r = sm_transmit_apdu(npactx, card, &apdu);
- else
- r = sc_transmit_apdu(card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0)
goto err;
@@ -1588,7 +1576,7 @@ err:
return r;
}
-static int npa_external_authenticate(struct sm_ctx *npactx, sc_card_t *card,
+static int npa_external_authenticate(sc_card_t *card,
const unsigned char *signature, size_t signature_len)
{
int r;
@@ -1607,10 +1595,7 @@ static int npa_external_authenticate(struct sm_ctx *npactx, sc_card_t *card,
apdu.datalen = signature_len;
apdu.lc = signature_len;
- if (npactx)
- r = sm_transmit_apdu(npactx, card, &apdu);
- else
- r = sc_transmit_apdu(card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0)
goto err;
@@ -1620,7 +1605,7 @@ err:
return r;
}
-int perform_terminal_authentication(struct sm_ctx *ctx, sc_card_t *card,
+int perform_terminal_authentication(sc_card_t *card,
const unsigned char **certs, const size_t *certs_lens,
const unsigned char *privkey, size_t privkey_len,
const unsigned char *auxiliary_data, size_t auxiliary_data_len)
@@ -1631,11 +1616,11 @@ int perform_terminal_authentication(struct sm_ctx *ctx, sc_card_t *card,
CVC_CERT *cvc_cert = NULL;
BUF_MEM *nonce = NULL, *signature = NULL;
- if (!card || !ctx->priv_data || !certs_lens || !certs) {
+ if (!card || !card->sm_ctx.info.cmd_data || !certs_lens || !certs) {
r = SC_ERROR_INVALID_ARGUMENTS;
goto err;
}
- struct npa_sm_ctx *eacsmctx = ctx->priv_data;
+ struct npa_sm_ctx *eacsmctx = card->sm_ctx.info.cmd_data;
while (*certs && *certs_lens) {
@@ -1650,7 +1635,7 @@ int perform_terminal_authentication(struct sm_ctx *ctx, sc_card_t *card,
}
cert = *certs;
- r = npa_mse_set_dst(ctx, card,
+ r = npa_mse_set_dst(card,
cvc_cert->body->certificate_authority_reference->data,
cvc_cert->body->certificate_authority_reference->length);
if (r < 0) {
@@ -1659,7 +1644,7 @@ int perform_terminal_authentication(struct sm_ctx *ctx, sc_card_t *card,
goto err;
}
- r = npa_verify(ctx, card, cert, cert_len);
+ r = npa_verify(card, cert, cert_len);
if (r < 0)
goto err;
@@ -1687,7 +1672,7 @@ int perform_terminal_authentication(struct sm_ctx *ctx, sc_card_t *card,
}
- r = npa_mse_set_at_ta(ctx, card, eacsmctx->ctx->ta_ctx->protocol,
+ r = npa_mse_set_at_ta(card, eacsmctx->ctx->ta_ctx->protocol,
cvc_cert->body->certificate_holder_reference->data,
cvc_cert->body->certificate_holder_reference->length,
eacsmctx->eph_pub_key->data, eacsmctx->eph_pub_key->length,
@@ -1704,7 +1689,7 @@ int perform_terminal_authentication(struct sm_ctx *ctx, sc_card_t *card,
r = SC_ERROR_INTERNAL;
goto err;
}
- r = npa_get_challenge(ctx, card, nonce->data, nonce->length);
+ r = npa_get_challenge(card, nonce->data, nonce->length);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get nonce for TA.");
goto err;
@@ -1728,7 +1713,7 @@ int perform_terminal_authentication(struct sm_ctx *ctx, sc_card_t *card,
r = SC_ERROR_INTERNAL;
goto err;
}
- r = npa_external_authenticate(ctx, card, signature->data, signature->length);
+ r = npa_external_authenticate(card, signature->data, signature->length);
err:
if (cvc_cert)
@@ -1739,15 +1724,14 @@ err:
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
}
-static int npa_mse_set_at_ca(struct sm_ctx *npactx, sc_card_t *card,
- int protocol)
+static int npa_mse_set_at_ca(sc_card_t *card, int protocol)
{
- return npa_mse_set_at(npactx, card, 0x41, protocol, NULL, 0, NULL, 0, NULL,
- 0, NULL, 0, NULL, NULL, NULL);
+ return npa_mse_set_at(card, 0x41, protocol, NULL, 0, NULL, 0, NULL, 0,
+ NULL, 0, NULL, NULL, NULL);
}
-static int npa_gen_auth_ca(struct sm_ctx *npactx, sc_card_t *card,
- const BUF_MEM *eph_pub_key, BUF_MEM **nonce, BUF_MEM **token)
+static int npa_gen_auth_ca(sc_card_t *card, const BUF_MEM *eph_pub_key,
+ BUF_MEM **nonce, BUF_MEM **token)
{
sc_apdu_t apdu;
NPA_GEN_AUTH_CA_C *c_data = NULL;
@@ -1786,10 +1770,7 @@ static int npa_gen_auth_ca(struct sm_ctx *npactx, sc_card_t *card,
apdu.resplen = sizeof resp;
apdu.resp = resp;
- if (npactx)
- r = sm_transmit_apdu(npactx, card, &apdu);
- else
- r = sc_transmit_apdu(card, &apdu);
+ r = sc_transmit_apdu(card, &apdu);
if (r < 0)
goto err;
@@ -1837,13 +1818,13 @@ err:
return r;
}
-int get_ef_card_security(struct sm_ctx *npactx, sc_card_t *card,
+int get_ef_card_security(sc_card_t *card,
u8 **ef_security, size_t *length_ef_security)
{
- return get_ef(npactx, card, SFID_EF_CARDSECURITY, ef_security, length_ef_security);
+ return get_ef(card, SFID_EF_CARDSECURITY, ef_security, length_ef_security);
}
-int perform_chip_authentication(struct sm_ctx *ctx, sc_card_t *card)
+int perform_chip_authentication(sc_card_t *card)
{
int r;
BUF_MEM *picc_pubkey = NULL, *nonce = NULL, *token = NULL,
@@ -1851,15 +1832,15 @@ int perform_chip_authentication(struct sm_ctx *ctx, sc_card_t *card)
unsigned char *ef_cardsecurity = NULL;
size_t ef_cardsecurity_len;
- if (!card || !ctx->priv_data) {
+ if (!card || !card->sm_ctx.info.cmd_data) {
r = SC_ERROR_INVALID_ARGUMENTS;
goto err;
}
- struct npa_sm_ctx *eacsmctx = ctx->priv_data;
+ struct npa_sm_ctx *eacsmctx = card->sm_ctx.info.cmd_data;
/* Passive Authentication */
- r = get_ef_card_security(ctx, card, &ef_cardsecurity, &ef_cardsecurity_len);
+ r = get_ef_card_security(card, &ef_cardsecurity, &ef_cardsecurity_len);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardSecurity.");
goto err;
@@ -1873,7 +1854,7 @@ int perform_chip_authentication(struct sm_ctx *ctx, sc_card_t *card)
}
- r = npa_mse_set_at_ca(ctx, card, eacsmctx->ctx->ca_ctx->protocol);
+ r = npa_mse_set_at_ca(card, eacsmctx->ctx->ca_ctx->protocol);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select protocol proberties "
"(MSE: Set AT failed).");
@@ -1888,7 +1869,7 @@ int perform_chip_authentication(struct sm_ctx *ctx, sc_card_t *card)
r = SC_ERROR_INTERNAL;
goto err;
}
- r = npa_gen_auth_ca(ctx, card, eph_pub_key, &nonce, &token);
+ r = npa_gen_auth_ca(card, eph_pub_key, &nonce, &token);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "(General Authenticate failed).");
goto err;
@@ -1977,7 +1958,7 @@ reset_ssc(struct npa_sm_ctx *eacsmctx)
}
static int
-npa_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx,
+npa_sm_encrypt(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *data, size_t datalen, u8 **enc)
{
BUF_MEM *encbuf = NULL, *databuf = NULL;
@@ -2018,7 +1999,7 @@ err:
}
static int
-npa_sm_decrypt(sc_card_t *card, const struct sm_ctx *ctx,
+npa_sm_decrypt(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *enc, size_t enclen, u8 **data)
{
BUF_MEM *encbuf = NULL, *databuf = NULL;
@@ -2059,7 +2040,7 @@ err:
}
static int
-npa_sm_authenticate(sc_card_t *card, const struct sm_ctx *ctx,
+npa_sm_authenticate(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *data, size_t datalen, u8 **macdata)
{
BUF_MEM *inbuf = NULL, *macbuf = NULL;
@@ -2107,7 +2088,7 @@ err:
}
static int
-npa_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
+npa_sm_verify_authentication(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *mac, size_t maclen,
const u8 *macdata, size_t macdatalen)
{
@@ -2182,7 +2163,7 @@ add_tag(unsigned char **asn1new, int constructed, int tag,
return newlen;
}
static int
-npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
+npa_sm_pre_transmit(sc_card_t *card, const struct iso_sm_ctx *ctx,
sc_apdu_t *apdu)
{
int r;
@@ -2396,7 +2377,7 @@ err:
}
static int
-npa_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx,
+npa_sm_post_transmit(sc_card_t *card, const struct iso_sm_ctx *ctx,
sc_apdu_t *sm_apdu)
{
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
@@ -2404,7 +2385,7 @@ npa_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx,
}
static int
-npa_sm_finish(sc_card_t *card, const struct sm_ctx *ctx,
+npa_sm_finish(sc_card_t *card, const struct iso_sm_ctx *ctx,
sc_apdu_t *apdu)
{
if (!card)
@@ -2440,7 +2421,7 @@ npa_sm_finish(sc_card_t *card, const struct sm_ctx *ctx,
}
static void
-npa_sm_clear_free(const struct sm_ctx *ctx)
+npa_sm_clear_free(const struct iso_sm_ctx *ctx)
{
if (ctx) {
struct npa_sm_ctx *eacsmctx = ctx->priv_data;
diff --git a/npa/src/npa/sm.h b/npa/src/npa/iso-sm.h
similarity index 59%
rename from npa/src/npa/sm.h
rename to npa/src/npa/iso-sm.h
index 7e8773c..b72c3f7 100644
--- a/npa/src/npa/sm.h
+++ b/npa/src/npa/iso-sm.h
@@ -18,7 +18,7 @@
*/
/**
* @file
- * @defgroup sm Secure Messaging (SM)
+ * @defgroup sm Interface to Secure Messaging (SM) defined in ISO 7816
* @{
*/
#ifndef _CCID_SM_H
@@ -36,10 +36,7 @@ extern "C" {
#define SM_NO_PADDING 0x02
/** Secure messaging context */
-struct sm_ctx {
- /** 1 if secure messaging is activated, 0 otherwise */
- unsigned char active;
-
+struct iso_sm_ctx {
/** data of the specific crypto implementation */
void *priv_data;
@@ -49,64 +46,72 @@ struct sm_ctx {
size_t block_length;
/** Call back function for authentication of data */
- int (*authenticate)(sc_card_t *card, const struct sm_ctx *ctx,
+ int (*authenticate)(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *data, size_t datalen, u8 **outdata);
/** Call back function for verifying authentication data */
- int (*verify_authentication)(sc_card_t *card, const struct sm_ctx *ctx,
+ int (*verify_authentication)(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *mac, size_t maclen,
const u8 *macdata, size_t macdatalen);
/** Call back function for encryption of data */
- int (*encrypt)(sc_card_t *card, const struct sm_ctx *ctx,
+ int (*encrypt)(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *data, size_t datalen, u8 **enc);
/** Call back function for decryption of data */
- int (*decrypt)(sc_card_t *card, const struct sm_ctx *ctx,
+ int (*decrypt)(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *enc, size_t enclen, u8 **data);
/** Call back function for actions before encoding and encryption of \a apdu */
- int (*pre_transmit)(sc_card_t *card, const struct sm_ctx *ctx,
+ int (*pre_transmit)(sc_card_t *card, const struct iso_sm_ctx *ctx,
sc_apdu_t *apdu);
/** Call back function for actions before decryption and decoding of \a sm_apdu */
- int (*post_transmit)(sc_card_t *card, const struct sm_ctx *ctx,
+ int (*post_transmit)(sc_card_t *card, const struct iso_sm_ctx *ctx,
sc_apdu_t *sm_apdu);
/** Call back function for actions after decrypting SM protected APDU */
- int (*finish)(sc_card_t *card, const struct sm_ctx *ctx,
+ int (*finish)(sc_card_t *card, const struct iso_sm_ctx *ctx,
sc_apdu_t *apdu);
/** Clears and frees private data */
- void (*clear_free)(const struct sm_ctx *ctx);
+ void (*clear_free)(const struct iso_sm_ctx *ctx);
};
/**
- * @brief Secure messaging wrapper for sc_transmit_apdu()
+ * @brief Clears and frees the SM context including private data
*
- * If secure messaging (SM) is activated in \a sctx and \a apdu is not already
- * SM protected, \a apdu is processed with the following steps:
- * \li call to \a sctx->pre_transmit
- * \li encrypt \a apdu calling \a sctx->encrypt
- * \li authenticate \a apdu calling \a sctx->authenticate
- * \li transmit SM protected \a apdu
- * \li verify SM protected \a apdu calling \a sctx->verify_authentication
- * \li decrypt SM protected \a apdu calling \a sctx->decrypt
- * \li copy decrypted/authenticated data and status bytes to \a apdu
+ * Calls \a sctx->clear_free() if available
*
* @param[in] sctx (optional)
- * @param[in] card
- * @param[in,out] apdu
- *
+ */
+void iso_sm_ctx_clear_free(struct iso_sm_ctx *sctx);
+
+/**
+ * @brief Creates a SM context
+ *
+ * @return SM context or NULL if an error occurred
+ */
+struct iso_sm_ctx *iso_sm_ctx_create(void);
+
+/**
+ * @brief Initializes a card for usage of the ISO SM driver
+ *
+ * If a SM module has been assigned previously to the card, it will be cleaned
+ * up.
+ *
+ * @param[in] card
+ * @param[in] sctx will NOT be freed automatically. \a sctx should be present
+ * for the time of the SM session.
+ *
* @return \c SC_SUCCESS or error code if an error occurred
*/
-int sm_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card,
- sc_apdu_t *apdu);
+int iso_sm_start(struct sc_card *card, struct iso_sm_ctx *sctx);
-/**
- * @brief Clears and frees private data of the SM context
+/**
+ * @brief Stops SM and frees allocated ressources.
*
- * Calls \a sctx->clear_free
- *
- * @param[in] sctx (optional)
+ * @param[in] card
+ *
+ * @return \c SC_SUCCESS or error code if an error occurred
*/
-void sm_ctx_clear_free(const struct sm_ctx *sctx);
+int sm_stop(struct sc_card *card);
#ifdef __cplusplus
}
diff --git a/npa/src/npa/npa.h b/npa/src/npa/npa.h
index 7659106..bb763a3 100644
--- a/npa/src/npa/npa.h
+++ b/npa/src/npa/npa.h
@@ -113,53 +113,50 @@ extern "C" {
const char *npa_secret_name(enum s_type pin_id);
-#ifdef BUERGERCLIENT_WORKAROUND
-int get_ef_card_access(sc_card_t *card,
- u8 **ef_cardaccess, size_t *length_ef_cardaccess);
-#endif
-
/**
- * @brief Get the reader's PACE capabilities
+ * @brief Get the PACE capabilities
*
* @param[in,out] bitmap where to store capabilities bitmap
* @note Since this code offers no support for terminal certificate, the bitmap is always \c PACE_BITMAP_PACE|PACE_BITMAP_EID
*
* @return \c SC_SUCCESS or error code if an error occurred
*/
-int GetReadersPACECapabilities(u8 *bitmap);
+int get_pace_capabilities(u8 *bitmap);
/**
* @brief Establish secure messaging using PACE
*
+ * Modifies \a card to use the ISO SM driver and initializes the data
+ * structures to use the established SM channel.
+ *
* Prints certificate description and card holder authorization template if
* given in a human readable form to stdout. If no secret is given, the user is
* asked for it. Only \a pace_input.pin_id is mandatory, the other members of
- * \a pace_input can be set to \c 0 or \c NULL.
+ * \a pace_input can be set to \c 0 or \c NULL respectively.
*
* The buffers in \a pace_output are allocated using \c realloc() and should be
* set to NULL, if empty. If an EF.CardAccess is already present, this file is
* reused and not fetched from the card.
*
* @param[in] oldpacectx (optional) Old SM context, if PACE is established in an existing SM channel
- * @param[in] card
+ * @param[in,out] card
* @param[in] pace_input
* @param[in,out] pace_output
- * @param[out] sctx
* @param[in] tr_version Version of TR-03110 to use with PACE
*
* @return \c SC_SUCCESS or error code if an error occurred
*/
-int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
+int perform_pace(sc_card_t *card,
struct establish_pace_channel_input pace_input,
struct establish_pace_channel_output *pace_output,
- struct sm_ctx *sctx, enum eac_tr_version tr_version);
+ enum eac_tr_version tr_version);
-int perform_terminal_authentication(struct sm_ctx *ctx, sc_card_t *card,
+int perform_terminal_authentication(sc_card_t *card,
const unsigned char **certs, const size_t *certs_lens,
const unsigned char *privkey, size_t privkey_len,
const unsigned char *auxiliary_data, size_t auxiliary_data_len);
-int perform_chip_authentication(struct sm_ctx *ctx, sc_card_t *card);
+int perform_chip_authentication(sc_card_t *card);
/**
* @brief Sends a reset retry counter APDU
@@ -169,7 +166,6 @@ int perform_chip_authentication(struct sm_ctx *ctx, sc_card_t *card);
* operation to be authorized either by an established PACE channel or by the
* effective authorization of the terminal's certificate.
*
- * @param[in] ctx (optional) NPA SM context
* @param[in] card
* @param[in] pin_id Type of secret (usually PIN or CAN). You may use enum s_type from \c .
* @param[in] ask_for_secret whether to ask the user for the secret (\c 1) or not (\c 0)
@@ -178,26 +174,24 @@ int perform_chip_authentication(struct sm_ctx *ctx, sc_card_t *card);
*
* @return \c SC_SUCCESS or error code if an error occurred
*/
-int npa_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
+int npa_reset_retry_counter(sc_card_t *card,
enum s_type pin_id, int ask_for_secret,
const char *new, size_t new_len);
/**
* @brief Send APDU to unblock the PIN
*
- * @param[in] ctx (optional) NPA SM context
* @param[in] card
*/
-#define npa_unblock_pin(ctx, card) \
- npa_reset_retry_counter(ctx, card, PACE_PIN, 0, NULL, 0)
+#define npa_unblock_pin(card) \
+ npa_reset_retry_counter(card, PACE_PIN, 0, NULL, 0)
/** Send APDU to set a new PIN
*
- * @param[in] ctx (optional) NPA SM context
* @param[in] card
* @param[in] newp (optional) new PIN
* @param[in] newplen (optional) length of \a new
*/
-#define npa_change_pin(ctx, card, newp, newplen) \
- npa_reset_retry_counter(ctx, card, PACE_PIN, 1, newp, newplen)
+#define npa_change_pin(card, newp, newplen) \
+ npa_reset_retry_counter(card, PACE_PIN, 1, newp, newplen)
#define NPA_FLAG_DISABLE_CHECKS 1
extern char npa_default_flags;
diff --git a/npa/src/scutil.c b/npa/src/scutil.c
index 6cf7a15..ed4803f 100644
--- a/npa/src/scutil.c
+++ b/npa/src/scutil.c
@@ -16,10 +16,14 @@
* You should have received a copy of the GNU General Public License along with
* ccid. If not, see .
*/
-#include "scutil.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
#include
#include
-#include
int initialize(int reader_id, const char *cdriver, int verbose,
sc_context_t **ctx, sc_reader_t **reader)
diff --git a/npa/src/sslutil.c b/npa/src/sslutil.c
deleted file mode 100644
index 6b7bab5..0000000
--- a/npa/src/sslutil.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2011 Frank Morgner
- *
- * This file is part of ccid.
- *
- * ccid is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * ccid 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 General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * ccid. If not, see .
- */