- using short apdus for mse:set at and generic authenticate. to make it work with the sm implementation

- added parameter oldpacectx to EstablishPACEChannel to allow a a new PACE connection inside an exitsting PACE connection (the output buffer of the latter connection must be provided since it stores the ef.cardaccess)
- added functionality to ask for the secret in pace_reset_retry_counter
- added macro pace_change_pin
- SWs were stored at the wrong place of the output buffer from EstablishPACEChannel, fixed.
- split up functionality of pace_test into multiple functions
- added new command line option to pace-tool to resume the pin. resuming the pin is not working, yet.


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@108 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2010-05-20 08:17:38 +00:00
parent d0a6668f58
commit 894d5be379
4 changed files with 232 additions and 153 deletions

View File

@@ -20,7 +20,6 @@
#include "pace.h" #include "pace.h"
#include "scutil.h" #include "scutil.h"
#include <opensc/log.h> #include <opensc/log.h>
#include <opensc/ui.h>
#include <openssl/pace.h> #include <openssl/pace.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@@ -31,9 +30,14 @@ static int verbose = 0;
static int doinfo = 0; static int doinfo = 0;
static u8 pin_id = 0; static u8 pin_id = 0;
static u8 dochangepin = 0; static u8 dochangepin = 0;
static u8 doresumepin = 0;
static u8 dotranslate = 1;
static const char *newpin = NULL; static const char *newpin = NULL;
static int usb_reader_num = -1; static int usb_reader_num = -1;
static const char *pin = NULL; static const char *pin = NULL;
static const char *puk = NULL;
static const char *can = NULL;
static const char *mrz = NULL;
static const char *cdriver = NULL; static const char *cdriver = NULL;
static sc_context_t *ctx = NULL; static sc_context_t *ctx = NULL;
@@ -46,7 +50,8 @@ static sc_reader_t *reader;
#define OPT_PUK 'u' #define OPT_PUK 'u'
#define OPT_CAN 'a' #define OPT_CAN 'a'
#define OPT_MRZ 'z' #define OPT_MRZ 'z'
#define OPT_CHANGE_PIN 'I' #define OPT_CHANGE_PIN 'C'
#define OPT_RESUME_PIN 'R'
#define OPT_VERBOSE 'v' #define OPT_VERBOSE 'v'
#define OPT_INFO 'o' #define OPT_INFO 'o'
#define OPT_CARD 'c' #define OPT_CARD 'c'
@@ -55,11 +60,12 @@ static const struct option options[] = {
{ "help", no_argument, NULL, OPT_HELP }, { "help", no_argument, NULL, OPT_HELP },
{ "reader", required_argument, NULL, OPT_READER }, { "reader", required_argument, NULL, OPT_READER },
{ "card-driver", required_argument, NULL, OPT_CARD }, { "card-driver", required_argument, NULL, OPT_CARD },
{ "pin", optional_argument, NULL, OPT_PIN }, { "pin", required_argument, NULL, OPT_PIN },
{ "puk", optional_argument, NULL, OPT_PUK }, { "puk", required_argument, NULL, OPT_PUK },
{ "can", optional_argument, NULL, OPT_CAN }, { "can", required_argument, NULL, OPT_CAN },
{ "mrz", optional_argument, NULL, OPT_MRZ }, { "mrz", required_argument, NULL, OPT_MRZ },
{ "new-pin", optional_argument, NULL, OPT_CHANGE_PIN }, { "new-pin", optional_argument, NULL, OPT_CHANGE_PIN },
{ "resume-pin", no_argument, NULL, OPT_RESUME_PIN },
{ "verbose", no_argument, NULL, OPT_VERBOSE }, { "verbose", no_argument, NULL, OPT_VERBOSE },
{ "info", no_argument, NULL, OPT_INFO }, { "info", no_argument, NULL, OPT_INFO },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
@@ -73,59 +79,16 @@ static const char *option_help[] = {
"Run PACE with CAN", "Run PACE with CAN",
"Run PACE with MRZ (insert MRZ without newlines)", "Run PACE with MRZ (insert MRZ without newlines)",
"Install a new PIN", "Install a new PIN",
"Resume PIN (use CAN to activate last retry of PIN authenticaten)",
"Use (several times) to be more verbose", "Use (several times) to be more verbose",
"Print version, available readers and drivers.", "Print version, available readers and drivers.",
}; };
int pace_change_p(struct sm_ctx *ctx, sc_card_t *card, enum s_type pin_id, int pace_get_channel(struct sm_ctx *oldpacectx, sc_card_t *card,
const char *newp, size_t newplen)
{
sc_ui_hints_t hints;
char *p = NULL;
int r;
if (!newplen || !newp) {
memset(&hints, 0, sizeof(hints));
hints.dialog_name = "ccid.PACE";
hints.card = card;
hints.prompt = NULL;
hints.obj_label = pace_secret_name(pin_id);
hints.usage = SC_UI_USAGE_NEW_PIN;
r = sc_ui_get_pin(&hints, &p);
if (r < 0) {
sc_error(card->ctx, "Could not read new %s (%s).\n",
hints.obj_label, sc_strerror(r));
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
}
newplen = strlen(p);
newp = p;
}
r = pace_reset_retry_counter(ctx, card, pin_id, newp, newplen);
if (p) {
OPENSSL_cleanse(p, newplen);
free(p);
}
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
}
int pace_test(sc_card_t *card,
enum s_type pin_id, const char *pin, size_t pinlen, enum s_type pin_id, const char *pin, size_t pinlen,
enum s_type new_pin_id, const char *new_pin, size_t new_pinlen) __u8 **out, size_t *outlen, struct sm_ctx *sctx)
{ {
u8 buf[0xff + 5]; u8 buf[0xff + 5];
char *read = NULL;
__u8 *out = NULL;
size_t outlen, readlen = 0, apdulen;
ssize_t linelen;
struct sm_ctx sctx;
sc_apdu_t apdu;
int r;
memset(&sctx, 0, sizeof(sctx));
memset(&apdu, 0, sizeof(apdu));
switch (pin_id) { switch (pin_id) {
case PACE_MRZ: case PACE_MRZ:
@@ -150,62 +113,64 @@ int pace_test(sc_card_t *card,
buf[3 + pinlen] = 0; // length_cert_desc buf[3 + pinlen] = 0; // length_cert_desc
buf[4 + pinlen]= 0; // length_cert_desc buf[4 + pinlen]= 0; // length_cert_desc
SC_TEST_RET(card->ctx, SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR,
EstablishPACEChannel(card, NULL, buf, &out, &outlen, &sctx), EstablishPACEChannel(oldpacectx, card, buf, out, outlen, sctx));
"Could not establish PACE channel."); }
printf("Established PACE channel.\n"); int pace_translate_apdus(struct sm_ctx *sctx, sc_card_t *card)
{
u8 buf[0xff + 5];
char *read = NULL;
size_t readlen = 0, apdulen;
sc_apdu_t apdu;
ssize_t linelen;
int r;
if (new_pin_id) { memset(&apdu, 0, sizeof(apdu));
SC_TEST_RET(card->ctx,
pace_change_p(&sctx, card, new_pin_id, new_pin, new_pinlen),
"Could not change PACE secret.");
printf("Changed %s.\n", pace_secret_name(new_pin_id));
r = SC_SUCCESS;
} else {
while (1) {
printf("Enter unencrypted APDU (empty line to exit)\n");
linelen = getline(&read, &readlen, stdin); while (1) {
if (linelen <= 1) { printf("Enter unencrypted APDU (empty line to exit)\n");
if (linelen < 0) {
r = SC_ERROR_INTERNAL; linelen = getline(&read, &readlen, stdin);
sc_error(card->ctx, "Could not read line"); if (linelen <= 1) {
} else { if (linelen < 0) {
r = SC_SUCCESS; r = SC_ERROR_INTERNAL;
printf("Thanks for flying with ccid\n"); sc_error(card->ctx, "Could not read line");
} } else {
break; r = SC_SUCCESS;
printf("Thanks for flying with ccid\n");
} }
break;
read[linelen - 1] = 0;
if (sc_hex_to_bin(read, buf, &apdulen) < 0) {
sc_error(card->ctx, "Could not format binary string");
}
r = build_apdu(card->ctx, buf, apdulen, &apdu);
if (r < 0) {
sc_error(card->ctx, "Could not format APDU");
continue;
}
apdu.resp = buf;
apdu.resplen = sizeof(buf);
r = pace_transmit_apdu(&sctx, card, &apdu);
if (r < 0) {
sc_error(card->ctx, "Could not send APDU: %s", sc_strerror(r));
continue;
}
printf("Decrypted APDU sw1=%02x sw2=%02x\n", apdu.sw1, apdu.sw2);
bin_print(stdout, "Decrypted APDU response data", apdu.resp, apdu.resplen);
} }
if (read) read[linelen - 1] = 0;
free(read); if (sc_hex_to_bin(read, buf, &apdulen) < 0) {
sc_error(card->ctx, "Could not format binary string");
}
r = build_apdu(card->ctx, buf, apdulen, &apdu);
if (r < 0) {
sc_error(card->ctx, "Could not format APDU");
continue;
}
apdu.resp = buf;
apdu.resplen = sizeof(buf);
r = pace_transmit_apdu(sctx, card, &apdu);
if (r < 0) {
sc_error(card->ctx, "Could not send APDU: %s", sc_strerror(r));
continue;
}
printf("Decrypted APDU sw1=%02x sw2=%02x\n", apdu.sw1, apdu.sw2);
bin_print(stdout, "Decrypted APDU response data", apdu.resp, apdu.resplen);
} }
err:
if (read)
free(read);
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
} }
@@ -213,9 +178,15 @@ int
main (int argc, char **argv) main (int argc, char **argv)
{ {
int i, oindex = 0; int i, oindex = 0;
__u8 *channeldata = NULL;
size_t channeldatalen;
struct sm_ctx sctx, tmpctx;
memset(&sctx, 0, sizeof(sctx));
memset(&tmpctx, 0, sizeof(tmpctx));
while (1) { while (1) {
i = getopt_long(argc, argv, "hr:i::u::a::z::I::voc:", options, &oindex); i = getopt_long(argc, argv, "hr:i:u:a:z:C::voc:", options, &oindex);
if (i == -1) if (i == -1)
break; break;
switch (i) { switch (i) {
@@ -239,25 +210,26 @@ main (int argc, char **argv)
doinfo++; doinfo++;
break; break;
case OPT_PUK: case OPT_PUK:
pin_id = PACE_PUK; puk = optarg;
pin = optarg;
break; break;
case OPT_PIN: case OPT_PIN:
pin_id = PACE_PIN;
pin = optarg; pin = optarg;
break; break;
case OPT_CAN: case OPT_CAN:
pin_id = PACE_CAN; can = optarg;
pin = optarg;
break; break;
case OPT_MRZ: case OPT_MRZ:
pin_id = PACE_MRZ; mrz = optarg;
pin = optarg;
break; break;
case OPT_CHANGE_PIN: case OPT_CHANGE_PIN:
dochangepin = 3; dochangepin = 1;
dotranslate = 0;
newpin = optarg; newpin = optarg;
break; break;
case OPT_RESUME_PIN:
doresumepin = 1;
dotranslate = 0;
break;
case '?': case '?':
/* fall through */ /* fall through */
default: default:
@@ -301,9 +273,75 @@ main (int argc, char **argv)
return 1; return 1;
} }
i = pace_test(card, pin_id, pin, !pin ? 0 : strlen(pin), if (doresumepin) {
dochangepin, newpin, !newpin ? 0 : strlen(newpin)); i = pace_get_channel(NULL, card,
PACE_CAN, can, can ? strlen(can) : 0,
&channeldata, &channeldatalen, &tmpctx);
if (i < 0)
goto err;
printf("Established PACE channel with CAN.\n");
i = pace_reset_retry_counter(&tmpctx, card, PACE_PIN, 0, NULL, 0);
if (i < 0)
goto err;
printf("Resumed PIN.\n");
i = pace_get_channel(&tmpctx, card,
PACE_PIN, pin, pin ? strlen(pin) : 0,
&channeldata, &channeldatalen, &sctx);
if (i < 0)
goto err;
printf("Established PACE channel with PIN.\n");
}
if (dochangepin) {
i = pace_get_channel(NULL, card,
PACE_PIN, pin, pin ? strlen(pin) : 0,
&channeldata, &channeldatalen, &sctx);
if (i < 0)
goto err;
printf("Established PACE channel with PIN.\n");
i = pace_change_pin(&sctx, card, newpin, newpin ? strlen(newpin) : 0);
if (i < 0)
goto err;
printf("Changed PIN.\n");
}
if (dotranslate) {
enum s_type id;
const char *s;
if (pin) {
id = PACE_PIN;
s = pin;
} else if (can) {
id = PACE_CAN;
s = can;
} else if (mrz) {
id = PACE_MRZ;
s = mrz;
} else if (puk) {
id = PACE_PUK;
s = puk;
} else {
fprintf(stderr, "Please provide PIN, CAN, MRZ or PUK.");
return 1;
}
i = pace_get_channel(NULL, card, id, s, s ? strlen(s) : 0,
&channeldata, &channeldatalen, &sctx);
if (i < 0)
goto err;
printf("Established PACE channel with %s.\n", pace_secret_name(id));
i = pace_translate_apdus(&sctx, card);
if (i < 0)
goto err;
}
err:
if (channeldata)
free(channeldata);
sc_disconnect_card(card, 0); sc_disconnect_card(card, 0);
sc_release_context(ctx); sc_release_context(ctx);

View File

@@ -28,6 +28,7 @@
#include <openssl/asn1t.h> #include <openssl/asn1t.h>
#include <openssl/buffer.h> #include <openssl/buffer.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h> #include <openssl/objects.h>
#include <openssl/pace.h> #include <openssl/pace.h>
#include <string.h> #include <string.h>
@@ -240,7 +241,7 @@ err:
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
} }
static int pace_mse_set_at(sc_card_t *card, static int pace_mse_set_at(const struct sm_ctx *oldpacectx, sc_card_t *card,
int protocol, int secret_key, int reference, u8 *sw1, u8 *sw2) int protocol, int secret_key, int reference, u8 *sw1, u8 *sw2)
{ {
sc_apdu_t apdu; sc_apdu_t apdu;
@@ -257,7 +258,7 @@ static int pace_mse_set_at(sc_card_t *card,
apdu.ins = 0x22; apdu.ins = 0x22;
apdu.p1 = 0xc1; apdu.p1 = 0xc1;
apdu.p2 = 0xa4; apdu.p2 = 0xa4;
apdu.cse = SC_APDU_CASE_3; apdu.cse = SC_APDU_CASE_3_SHORT;
apdu.flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL; apdu.flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL;
data = PACE_MSE_SET_AT_C_new(); data = PACE_MSE_SET_AT_C_new();
@@ -294,7 +295,10 @@ static int pace_mse_set_at(sc_card_t *card,
bin_log(card->ctx, "MSE:Set AT command data", apdu.data, apdu.datalen); bin_log(card->ctx, "MSE:Set AT command data", apdu.data, apdu.datalen);
r = sc_transmit_apdu(card, &apdu); if (oldpacectx)
r = pace_transmit_apdu(oldpacectx, card, &apdu);
else
r = sc_transmit_apdu(card, &apdu);
if (r < 0) if (r < 0)
goto err; goto err;
@@ -355,7 +359,7 @@ err:
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
} }
static int pace_gen_auth(sc_card_t *card, static int pace_gen_auth(const struct sm_ctx *oldpacectx, sc_card_t *card,
int step, const u8 *in, size_t in_len, u8 **out, size_t *out_len) int step, const u8 *in, size_t in_len, u8 **out, size_t *out_len)
{ {
sc_apdu_t apdu; sc_apdu_t apdu;
@@ -367,7 +371,7 @@ static int pace_gen_auth(sc_card_t *card,
memset(&apdu, 0, sizeof apdu); memset(&apdu, 0, sizeof apdu);
apdu.cla = 0x10; apdu.cla = 0x10;
apdu.ins = 0x86; apdu.ins = 0x86;
apdu.cse = SC_APDU_CASE_4; apdu.cse = SC_APDU_CASE_4_SHORT;
apdu.flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL; apdu.flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL;
c_data = PACE_GEN_AUTH_C_new(); c_data = PACE_GEN_AUTH_C_new();
@@ -423,7 +427,10 @@ static int pace_gen_auth(sc_card_t *card,
apdu.resplen = maxresp; apdu.resplen = maxresp;
apdu.resp = malloc(apdu.resplen); apdu.resp = malloc(apdu.resplen);
r = sc_transmit_apdu(card, &apdu); if (oldpacectx)
r = pace_transmit_apdu(oldpacectx, card, &apdu);
else
r = sc_transmit_apdu(card, &apdu);
if (r < 0) if (r < 0)
goto err; goto err;
@@ -542,9 +549,30 @@ err:
int int
pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card, pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
enum s_type pin_id, const char *new, size_t new_len) enum s_type pin_id, int ask_for_secret,
const char *new, size_t new_len)
{ {
sc_apdu_t apdu; sc_apdu_t apdu;
sc_ui_hints_t hints;
char *p = NULL;
int r;
if (ask_for_secret && (!new || !new_len)) {
memset(&hints, 0, sizeof(hints));
hints.dialog_name = "ccid.PACE";
hints.card = card;
hints.prompt = NULL;
hints.obj_label = pace_secret_name(PACE_PIN);
hints.usage = SC_UI_USAGE_NEW_PIN;
r = sc_ui_get_pin(&hints, &p);
if (r < 0) {
sc_error(card->ctx, "Could not read new %s (%s).\n",
hints.obj_label, sc_strerror(r));
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
}
new_len = strlen(p);
new = p;
}
memset(&apdu, 0, sizeof apdu); memset(&apdu, 0, sizeof apdu);
apdu.ins = 0x2C; apdu.ins = 0x2C;
@@ -562,7 +590,14 @@ pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
apdu.cse = SC_APDU_CASE_1; apdu.cse = SC_APDU_CASE_1;
} }
return pace_transmit_apdu(ctx, card, &apdu); r = pace_transmit_apdu(ctx, card, &apdu);
if (p) {
OPENSSL_cleanse(p, new_len);
free(p);
}
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
} }
static PACE_SEC * static PACE_SEC *
@@ -607,12 +642,12 @@ void debug_ossl(sc_context_t *ctx) {
} }
} }
int EstablishPACEChannel(sc_card_t *card, const struct pace_sm_ctx *oldctx, int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
const __u8 *in, __u8 **out, size_t *outlen, struct sm_ctx *sctx) const __u8 *in, __u8 **out, size_t *outlen, struct sm_ctx *sctx)
{ {
__u8 pin_id; __u8 pin_id;
size_t length_chat, length_pin, length_cert_desc, length_ef_cardaccess; size_t length_chat, length_pin, length_cert_desc, length_ef_cardaccess;
const __u8 *chat, *pin, *certificate_description, *p; const __u8 *chat, *pin, *certificate_description;
__u8 *ef_cardaccess = NULL; __u8 *ef_cardaccess = NULL;
PACEInfo *info = NULL; PACEInfo *info = NULL;
uint16_t word; uint16_t word;
@@ -624,6 +659,8 @@ int EstablishPACEChannel(sc_card_t *card, const struct pace_sm_ctx *oldctx,
PACE_CTX *pctx = NULL; PACE_CTX *pctx = NULL;
int r, second_execution; int r, second_execution;
if (!card)
return SC_ERROR_INVALID_ARGUMENTS;
if (!in || !out || !outlen) if (!in || !out || !outlen)
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
@@ -645,18 +682,8 @@ int EstablishPACEChannel(sc_card_t *card, const struct pace_sm_ctx *oldctx,
certificate_description = in; certificate_description = in;
if (*out) if (!*out) {
second_execution = 1;
else
second_execution = 0; second_execution = 0;
enc_nonce = BUF_MEM_new();
if (!enc_nonce) {
r = SC_ERROR_INTERNAL;
debug_ossl(card->ctx);
goto err;
}
if (!second_execution) {
r = get_ef_card_access(card, &ef_cardaccess, &length_ef_cardaccess); r = get_ef_card_access(card, &ef_cardaccess, &length_ef_cardaccess);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not get EF.CardAccess."); sc_error(card->ctx, "Could not get EF.CardAccess.");
@@ -667,19 +694,23 @@ int EstablishPACEChannel(sc_card_t *card, const struct pace_sm_ctx *oldctx,
r = SC_ERROR_OUT_OF_MEMORY; r = SC_ERROR_OUT_OF_MEMORY;
goto err; goto err;
} }
word = htons(length_ef_cardaccess); word = length_ef_cardaccess;
memcpy(*out + 2, &word, 2); word = htons(word);
memcpy(*out + 2, &word, sizeof word);
memcpy(*out + 4, ef_cardaccess, length_ef_cardaccess); memcpy(*out + 4, ef_cardaccess, length_ef_cardaccess);
/* XXX CAR */ /* XXX CAR */
(*out)[length_ef_cardaccess + 2] = 0; /*(*out)[length_ef_cardaccess + 2] = 0;*/
/* XXX CARprev */ /* XXX CARprev */
(*out)[length_ef_cardaccess + 3] = 0; /*(*out)[length_ef_cardaccess + 3] = 0;*/
} else { } else {
p = *out + 2; second_execution = 1;
length_ef_cardaccess = ntohs(*p); memcpy(&word, *out + 2, sizeof word);
word = ntohs(word);
length_ef_cardaccess = word;
ef_cardaccess = *out + 4; ef_cardaccess = *out + 4;
} }
bin_log(card->ctx, "EF.CardAccess", ef_cardaccess, length_ef_cardaccess); bin_log(card->ctx, "EF.CardAccess", ef_cardaccess, length_ef_cardaccess);
if (!parse_ef_card_access(ef_cardaccess, length_ef_cardaccess, if (!parse_ef_card_access(ef_cardaccess, length_ef_cardaccess,
&info, &static_dp)) { &info, &static_dp)) {
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
@@ -687,13 +718,20 @@ int EstablishPACEChannel(sc_card_t *card, const struct pace_sm_ctx *oldctx,
sc_error(card->ctx, "Could not parse EF.CardAccess."); sc_error(card->ctx, "Could not parse EF.CardAccess.");
goto err; goto err;
} }
r = pace_mse_set_at(card, info->protocol, pin_id, 1, (*out)+2, (*out)+3);
r = pace_mse_set_at(oldpacectx, card, info->protocol, pin_id, 1, *out, *out+1);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not select protocol proberties " sc_error(card->ctx, "Could not select protocol proberties "
"(MSE: Set AT)."); "(MSE: Set AT).");
goto err; goto err;
} }
r = pace_gen_auth(card, 1, NULL, 0, (u8 **) &enc_nonce->data, enc_nonce = BUF_MEM_new();
if (!enc_nonce) {
r = SC_ERROR_INTERNAL;
debug_ossl(card->ctx);
goto err;
}
r = pace_gen_auth(oldpacectx, card, 1, NULL, 0, (u8 **) &enc_nonce->data,
&enc_nonce->length); &enc_nonce->length);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not get encrypted nonce from card " sc_error(card->ctx, "Could not get encrypted nonce from card "
@@ -726,7 +764,7 @@ int EstablishPACEChannel(sc_card_t *card, const struct pace_sm_ctx *oldctx,
debug_ossl(card->ctx); debug_ossl(card->ctx);
goto err; goto err;
} }
r = pace_gen_auth(card, 2, (u8 *) mdata->data, mdata->length, r = pace_gen_auth(oldpacectx, card, 2, (u8 *) mdata->data, mdata->length,
(u8 **) &mdata_opp->data, &mdata_opp->length); (u8 **) &mdata_opp->data, &mdata_opp->length);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not exchange mapping data with card " sc_error(card->ctx, "Could not exchange mapping data with card "
@@ -744,7 +782,7 @@ int EstablishPACEChannel(sc_card_t *card, const struct pace_sm_ctx *oldctx,
debug_ossl(card->ctx); debug_ossl(card->ctx);
goto err; goto err;
} }
r = pace_gen_auth(card, 3, (u8 *) pub->data, pub->length, r = pace_gen_auth(oldpacectx, card, 3, (u8 *) pub->data, pub->length,
(u8 **) &pub_opp->data, &pub_opp->length); (u8 **) &pub_opp->data, &pub_opp->length);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not exchange ephemeral public key with card " sc_error(card->ctx, "Could not exchange ephemeral public key with card "
@@ -769,7 +807,7 @@ int EstablishPACEChannel(sc_card_t *card, const struct pace_sm_ctx *oldctx,
debug_ossl(card->ctx); debug_ossl(card->ctx);
goto err; goto err;
} }
r = pace_gen_auth(card, 4, (u8 *) token->data, token->length, r = pace_gen_auth(oldpacectx, card, 4, (u8 *) token->data, token->length,
(u8 **) &token_opp->data, &token_opp->length); (u8 **) &token_opp->data, &token_opp->length);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not exchange authentication token with card " sc_error(card->ctx, "Could not exchange authentication token with card "
@@ -1078,7 +1116,7 @@ incerr:
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
} }
int pace_transmit_apdu(struct sm_ctx *ctx, sc_card_t *card, int pace_transmit_apdu(const struct sm_ctx *ctx, sc_card_t *card,
sc_apdu_t *apdu) sc_apdu_t *apdu)
{ {
int r; int r;

View File

@@ -61,13 +61,16 @@ int pace_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
int GetReadersPACECapabilities(sc_card_t *card, const __u8 int GetReadersPACECapabilities(sc_card_t *card, const __u8
*in, __u8 **out, size_t *outlen); *in, __u8 **out, size_t *outlen);
int EstablishPACEChannel(sc_card_t *card, const struct pace_sm_ctx *oldctx, int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
const __u8 *in, __u8 **out, size_t *outlen, struct sm_ctx *sctx) const __u8 *in, __u8 **out, size_t *outlen, struct sm_ctx *sctx);
int pace_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card, int pace_transmit_apdu(const struct sm_ctx *sctx, sc_card_t *card,
sc_apdu_t *apdu); sc_apdu_t *apdu);
int pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card, int pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
enum s_type pin_id, const char *new, size_t new_len); enum s_type pin_id, int ask_for_secret,
const char *new, size_t new_len);
#define pace_change_pin(ctx, card, newp, newplen) \
pace_reset_retry_counter(ctx, card, PACE_PIN, 1, newp, newplen)
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -257,7 +257,7 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
if ((apdu->cla & 0x0C) == 0x0C) { if ((apdu->cla & 0x0C) == 0x0C) {
r = SC_ERROR_INVALID_ARGUMENTS; r = SC_ERROR_INVALID_ARGUMENTS;
sc_error(card->ctx, "Given APDU is already protected with some secure messaging."); sc_error(card->ctx, "Given APDU is already protected with some secure messaging");
goto err; goto err;
} }
@@ -561,13 +561,13 @@ int sm_transmit_apdu(const struct sm_ctx *sctx, sc_card_t *card,
sm_apdu.resplen = sizeof rbuf; sm_apdu.resplen = sizeof rbuf;
SC_TEST_RET(card->ctx, sm_encrypt(sctx, card, apdu, &sm_apdu), SC_TEST_RET(card->ctx, sm_encrypt(sctx, card, apdu, &sm_apdu),
"Could not encrypt APDU."); "Could not encrypt APDU");
SC_TEST_RET(card->ctx, sc_transmit_apdu(card, &sm_apdu), SC_TEST_RET(card->ctx, sc_transmit_apdu(card, &sm_apdu),
"Could not transmit SM APDU."); "Could not transmit SM APDU");
SC_TEST_RET(card->ctx, sm_decrypt(sctx, card, &sm_apdu, apdu), SC_TEST_RET(card->ctx, sm_decrypt(sctx, card, &sm_apdu, apdu),
"Could not decrypt APDU."); "Could not decrypt APDU");
SC_TEST_RET(card->ctx, sc_check_sw(card, apdu->sw1, apdu->sw2), SC_TEST_RET(card->ctx, sc_check_sw(card, apdu->sw1, apdu->sw2),
"Card returned error."); "Card returned error");
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS); SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
} }