- made establishpacechannel output independant from any byte order conversion.
little endian handling is done by the ccid-part. git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@215 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
285
ccid/src/ccid.c
285
ccid/src/ccid.c
@@ -769,6 +769,205 @@ write_pin(sc_apdu_t *apdu, struct sc_pin_cmd_pin *pin, uint8_t blocksize,
|
|||||||
blocksize - justify_offset, pin, encoding, sc_result);
|
blocksize - justify_offset, pin, encoding, sc_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
|
||||||
|
const __u8 *abData, size_t abDatalen,
|
||||||
|
__u8 **abDataOut, size_t *abDataOutLen)
|
||||||
|
{
|
||||||
|
struct establish_pace_channel_input pace_input;
|
||||||
|
struct establish_pace_channel_output pace_output;
|
||||||
|
size_t parsed = 0;
|
||||||
|
int sc_result;
|
||||||
|
__le16 word;
|
||||||
|
__u8 *p;
|
||||||
|
|
||||||
|
if (!abDataOut || !abDataOutLen)
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
|
memset(&pace_input, 0, sizeof(pace_input));
|
||||||
|
memset(&pace_output, 0, sizeof(pace_output));
|
||||||
|
|
||||||
|
|
||||||
|
if (abDatalen < parsed+1) {
|
||||||
|
sc_error(ctx, "Buffer too small, could not get PinID");
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
pace_input.pin_id = abData[parsed];
|
||||||
|
parsed++;
|
||||||
|
|
||||||
|
|
||||||
|
if (abDatalen < parsed+1) {
|
||||||
|
sc_error(ctx, "Buffer too small, could not get lengthCHAT");
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
pace_input.chat_length = abData[parsed];
|
||||||
|
parsed++;
|
||||||
|
|
||||||
|
if (abDatalen < parsed+pace_input.chat_length) {
|
||||||
|
sc_error(ctx, "Buffer too small, could not get CHAT");
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
pace_input.chat = &abData[parsed];
|
||||||
|
parsed += pace_input.chat_length;
|
||||||
|
/* XXX make this human readable */
|
||||||
|
if (pace_input.chat_length)
|
||||||
|
bin_log(ctx, "Card holder authorization template",
|
||||||
|
pace_input.chat, pace_input.chat_length);
|
||||||
|
|
||||||
|
|
||||||
|
if (abDatalen < parsed+1) {
|
||||||
|
sc_error(ctx, "Buffer too small, could not get lengthPIN");
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
pace_input.pin_length = abData[parsed];
|
||||||
|
parsed++;
|
||||||
|
|
||||||
|
if (abDatalen < parsed+pace_input.pin_length) {
|
||||||
|
sc_error(ctx, "Buffer too small, could not get PIN");
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
pace_input.pin = &abData[parsed];
|
||||||
|
parsed += pace_input.pin_length;
|
||||||
|
|
||||||
|
|
||||||
|
if (abDatalen < parsed+sizeof(word)) {
|
||||||
|
sc_error(ctx, "Buffer too small, could not get lengthCertificateDescription");
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
memcpy(&word, &abData[parsed], sizeof word);
|
||||||
|
pace_input.certificate_description_length = __le16_to_cpu(word);
|
||||||
|
parsed += sizeof word;
|
||||||
|
|
||||||
|
if (abDatalen < parsed+pace_input.certificate_description_length) {
|
||||||
|
sc_error(ctx, "Buffer too small, could not get CertificateDescription");
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
pace_input.certificate_description = &abData[parsed];
|
||||||
|
parsed += pace_input.certificate_description_length;
|
||||||
|
/* XXX make this human readable */
|
||||||
|
if (pace_input.certificate_description_length)
|
||||||
|
bin_log(ctx, "Certificate description",
|
||||||
|
pace_input.certificate_description,
|
||||||
|
pace_input.certificate_description_length);
|
||||||
|
|
||||||
|
|
||||||
|
/*if (sc_reset(card) < 0)*/
|
||||||
|
/*sc_error(ctx, "Could not reset card, will continue anyway");*/
|
||||||
|
|
||||||
|
sc_result = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
|
||||||
|
&sctx);
|
||||||
|
if (sc_result < 0)
|
||||||
|
return sc_result;
|
||||||
|
|
||||||
|
|
||||||
|
p = realloc(*abDataOut, 2 + /* Statusbytes */
|
||||||
|
2+pace_output.ef_cardaccess_length + /* EF.CardAccess */
|
||||||
|
1+pace_output.recent_car_length + /* Most recent CAR */
|
||||||
|
1+pace_output.previous_car_length + /* Previous CAR */
|
||||||
|
2+pace_output.id_icc_length); /* XXX */
|
||||||
|
if (!p)
|
||||||
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
*abDataOut = p;
|
||||||
|
|
||||||
|
|
||||||
|
*p = pace_output.mse_set_at_sw1;
|
||||||
|
p += 1;
|
||||||
|
|
||||||
|
*p = pace_output.mse_set_at_sw2;
|
||||||
|
p += 1;
|
||||||
|
|
||||||
|
|
||||||
|
if (pace_output.ef_cardaccess_length > 0xffff) {
|
||||||
|
sc_error(ctx, "EF.CardAcces %u bytes too long",
|
||||||
|
pace_output.ef_cardaccess_length-0xffff);
|
||||||
|
return SC_ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
word = __cpu_to_le16(pace_output.ef_cardaccess_length);
|
||||||
|
memcpy(p, &word, sizeof word);
|
||||||
|
p += sizeof word;
|
||||||
|
|
||||||
|
memcpy(p, pace_output.ef_cardaccess,
|
||||||
|
pace_output.ef_cardaccess_length);
|
||||||
|
p += pace_output.ef_cardaccess_length;
|
||||||
|
|
||||||
|
|
||||||
|
if (pace_output.recent_car_length > 0xff) {
|
||||||
|
sc_error(ctx, "Most recent CAR %u bytes too long",
|
||||||
|
pace_output.recent_car_length-0xff);
|
||||||
|
return SC_ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
*p = pace_output.recent_car_length;
|
||||||
|
p += 1;
|
||||||
|
|
||||||
|
memcpy(p, pace_output.recent_car,
|
||||||
|
pace_output.recent_car_length);
|
||||||
|
p += pace_output.recent_car_length;
|
||||||
|
|
||||||
|
|
||||||
|
if (pace_output.previous_car_length > 0xff) {
|
||||||
|
sc_error(ctx, "Most previous CAR %u bytes too long",
|
||||||
|
pace_output.previous_car_length-0xff);
|
||||||
|
return SC_ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
*p = pace_output.previous_car_length;
|
||||||
|
p += 1;
|
||||||
|
|
||||||
|
memcpy(p, pace_output.previous_car,
|
||||||
|
pace_output.previous_car_length);
|
||||||
|
p += pace_output.previous_car_length;
|
||||||
|
|
||||||
|
|
||||||
|
if (pace_output.id_icc_length > 0xffff) {
|
||||||
|
sc_error(ctx, "ID ICC %u bytes too long",
|
||||||
|
pace_output.id_icc_length-0xffff);
|
||||||
|
return SC_ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
word = __cpu_to_le16(pace_output.id_icc_length);
|
||||||
|
memcpy(p, &word, sizeof word);
|
||||||
|
p += sizeof word;
|
||||||
|
|
||||||
|
memcpy(p, pace_output.id_icc,
|
||||||
|
pace_output.id_icc_length);
|
||||||
|
p += pace_output.id_icc_length;
|
||||||
|
|
||||||
|
|
||||||
|
*abDataOutLen = 2 +
|
||||||
|
2+pace_output.ef_cardaccess_length +
|
||||||
|
1+pace_output.recent_car_length +
|
||||||
|
1+pace_output.previous_car_length +
|
||||||
|
2+pace_output.id_icc_length;
|
||||||
|
|
||||||
|
return SC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
perform_PC_to_RDR_Secure_GetReadersPACECapabilities(__u8 **abDataOut,
|
||||||
|
size_t *abDataOutLen)
|
||||||
|
{
|
||||||
|
int sc_result;
|
||||||
|
__u8 *result;
|
||||||
|
|
||||||
|
if (!abDataOut || !abDataOutLen)
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
|
result = realloc(*abDataOut, 2);
|
||||||
|
if (!result)
|
||||||
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
*abDataOut = result;
|
||||||
|
|
||||||
|
/* lengthBitMap */
|
||||||
|
*result = 1;
|
||||||
|
result++;
|
||||||
|
|
||||||
|
sc_result = GetReadersPACECapabilities(result);
|
||||||
|
if (sc_result < 0)
|
||||||
|
return sc_result;
|
||||||
|
|
||||||
|
*abDataOutLen = 2;
|
||||||
|
|
||||||
|
return SC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outlen)
|
perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outlen)
|
||||||
{
|
{
|
||||||
@@ -779,10 +978,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
|
|||||||
const __u8* abData = in + sizeof *request;
|
const __u8* abData = in + sizeof *request;
|
||||||
size_t abDatalen = inlen - sizeof *request;
|
size_t abDatalen = inlen - sizeof *request;
|
||||||
u8 *abDataOut = NULL;
|
u8 *abDataOut = NULL;
|
||||||
size_t resplen = 0, parsed;
|
size_t resplen = 0;
|
||||||
__le16 word;
|
|
||||||
struct establish_pace_channel_input pace_input;
|
|
||||||
struct establish_pace_channel_output pace_output;
|
|
||||||
RDR_to_PC_DataBlock_t *result;
|
RDR_to_PC_DataBlock_t *result;
|
||||||
|
|
||||||
if (!in || !out || !outlen)
|
if (!in || !out || !outlen)
|
||||||
@@ -796,8 +992,6 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
|
|||||||
|
|
||||||
memset(&curr_pin, 0, sizeof(curr_pin));
|
memset(&curr_pin, 0, sizeof(curr_pin));
|
||||||
memset(&new_pin, 0, sizeof(new_pin));
|
memset(&new_pin, 0, sizeof(new_pin));
|
||||||
memset(&pace_input, 0, sizeof(pace_input));
|
|
||||||
memset(&pace_output, 0, sizeof(pace_output));
|
|
||||||
|
|
||||||
if (request->bSlot > sizeof *card_in_slot) {
|
if (request->bSlot > sizeof *card_in_slot) {
|
||||||
sc_error(ctx, "Received request to invalid slot (bSlot=0x%02x)", request->bSlot);
|
sc_error(ctx, "Received request to invalid slot (bSlot=0x%02x)", request->bSlot);
|
||||||
@@ -858,82 +1052,15 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
|
|||||||
#ifdef WITH_PACE
|
#ifdef WITH_PACE
|
||||||
case 0x10:
|
case 0x10:
|
||||||
|
|
||||||
if (abDatalen < 1) {
|
sc_result = perform_PC_to_RDR_Secure_GetReadersPACECapabilities(
|
||||||
sc_error(ctx, "Not enough data for input of GetReadersPACECapabilities");
|
&abDataOut, &resplen);
|
||||||
sc_result = SC_ERROR_INVALID_DATA;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_result =
|
|
||||||
GetReadersPACECapabilities(card_in_slot[request->bSlot],
|
|
||||||
abData + 1, abDatalen-1, &abDataOut, &resplen);
|
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
parsed = 1;
|
|
||||||
|
|
||||||
if (abDatalen < parsed+1) {
|
sc_result = perform_PC_to_RDR_Secure_EstablishPACEChannel(
|
||||||
sc_error(ctx, "Buffer too small, could not get PinID");
|
card_in_slot[request->bSlot], abData+1, abDatalen-1,
|
||||||
goto err;
|
&abDataOut, &resplen);
|
||||||
}
|
|
||||||
pace_input.pin_id = abData[parsed];
|
|
||||||
parsed++;
|
|
||||||
|
|
||||||
if (abDatalen < parsed+1) {
|
|
||||||
sc_error(ctx, "Buffer too small, could not get lengthCHAT");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
pace_input.chat_length = abData[parsed];
|
|
||||||
parsed++;
|
|
||||||
|
|
||||||
if (abDatalen < parsed+pace_input.chat_length) {
|
|
||||||
sc_error(ctx, "Buffer too small, could not get CHAT");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
pace_input.chat = &abData[parsed];
|
|
||||||
parsed += pace_input.chat_length;
|
|
||||||
/* XXX make this human readable */
|
|
||||||
if (pace_input.chat_length)
|
|
||||||
bin_log(ctx, "Card holder authorization template",
|
|
||||||
pace_input.chat, pace_input.chat_length);
|
|
||||||
|
|
||||||
if (abDatalen < parsed+1) {
|
|
||||||
sc_error(ctx, "Buffer too small, could not get lengthPIN");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
pace_input.pin_length = abData[parsed];
|
|
||||||
parsed++;
|
|
||||||
|
|
||||||
if (abDatalen < parsed+pace_input.pin_length) {
|
|
||||||
sc_error(ctx, "Buffer too small, could not get PIN");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
pace_input.pin = &abData[parsed];
|
|
||||||
parsed += pace_input.pin_length;
|
|
||||||
|
|
||||||
if (abDatalen < parsed+sizeof(word)) {
|
|
||||||
sc_error(ctx, "Buffer too small, could not get lengthCertificateDescription");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
memcpy(&word, &abData[parsed], sizeof word);
|
|
||||||
pace_input.certificate_description_length = __le16_to_cpu(word);
|
|
||||||
parsed += sizeof word;
|
|
||||||
|
|
||||||
if (abDatalen < parsed+pace_input.certificate_description_length) {
|
|
||||||
sc_error(ctx, "Buffer too small, could not get CertificateDescription");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
pace_input.certificate_description = &abData[parsed];
|
|
||||||
parsed+= pace_input.certificate_description_length;
|
|
||||||
/* XXX make this human readable */
|
|
||||||
if (pace_input.certificate_description_length)
|
|
||||||
bin_log(ctx, "Certificate description",
|
|
||||||
pace_input.certificate_description,
|
|
||||||
pace_input.certificate_description_length);
|
|
||||||
|
|
||||||
sc_result = EstablishPACEChannel(NULL,
|
|
||||||
card_in_slot[request->bSlot], pace_input,
|
|
||||||
&abDataOut, &resplen, &sctx);
|
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -1079,7 +1206,7 @@ err:
|
|||||||
} else {
|
} else {
|
||||||
*outlen = sizeof *result;
|
*outlen = sizeof *result;
|
||||||
debug_sc_result(sc_result);
|
debug_sc_result(sc_result);
|
||||||
sc_error(ctx, "Could not get memory for response apdu."
|
sc_error(ctx, "Some error occurred."
|
||||||
" Returning package without payload.");
|
" Returning package without payload.");
|
||||||
}
|
}
|
||||||
result->bError = get_bError(sc_result);
|
result->bError = get_bError(sc_result);
|
||||||
|
|||||||
@@ -166,17 +166,17 @@ 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;
|
size_t channeldatalen;
|
||||||
struct sm_ctx sctx, tmpctx;
|
struct sm_ctx sctx, tmpctx;
|
||||||
struct establish_pace_channel_input pace_input;
|
struct establish_pace_channel_input pace_input;
|
||||||
|
struct establish_pace_channel_output pace_output;
|
||||||
time_t t_start, t_end;
|
time_t t_start, t_end;
|
||||||
u8 *out = NULL;
|
|
||||||
size_t outlen;
|
size_t outlen;
|
||||||
|
|
||||||
memset(&sctx, 0, sizeof(sctx));
|
memset(&sctx, 0, sizeof(sctx));
|
||||||
memset(&tmpctx, 0, sizeof(tmpctx));
|
memset(&tmpctx, 0, sizeof(tmpctx));
|
||||||
memset(&pace_input, 0, sizeof(pace_input));
|
memset(&pace_input, 0, sizeof(pace_input));
|
||||||
|
memset(&pace_output, 0, sizeof(pace_output));
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
i = getopt_long(argc, argv, "hr:i::u::a::z::C:D:N::RUtvoc:", options, &oindex);
|
i = getopt_long(argc, argv, "hr:i::u::a::z::C:D:N::RUtvoc:", options, &oindex);
|
||||||
@@ -311,7 +311,7 @@ main (int argc, char **argv)
|
|||||||
pace_input.pin_length = 0;
|
pace_input.pin_length = 0;
|
||||||
}
|
}
|
||||||
t_start = time(NULL);
|
t_start = time(NULL);
|
||||||
i = EstablishPACEChannel(NULL, card, pace_input, &out, &outlen,
|
i = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
|
||||||
&tmpctx);
|
&tmpctx);
|
||||||
t_end = time(NULL);
|
t_end = time(NULL);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
@@ -328,7 +328,7 @@ main (int argc, char **argv)
|
|||||||
pace_input.pin_length = 0;
|
pace_input.pin_length = 0;
|
||||||
}
|
}
|
||||||
t_start = time(NULL);
|
t_start = time(NULL);
|
||||||
i = EstablishPACEChannel(&tmpctx, card, pace_input, &out, &outlen,
|
i = EstablishPACEChannel(&tmpctx, card, pace_input, &pace_output,
|
||||||
&sctx);
|
&sctx);
|
||||||
t_end = time(NULL);
|
t_end = time(NULL);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
@@ -347,7 +347,7 @@ main (int argc, char **argv)
|
|||||||
pace_input.pin_length = 0;
|
pace_input.pin_length = 0;
|
||||||
}
|
}
|
||||||
t_start = time(NULL);
|
t_start = time(NULL);
|
||||||
i = EstablishPACEChannel(NULL, card, pace_input, &out, &outlen,
|
i = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
|
||||||
&sctx);
|
&sctx);
|
||||||
t_end = time(NULL);
|
t_end = time(NULL);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
@@ -371,7 +371,7 @@ main (int argc, char **argv)
|
|||||||
pace_input.pin_length = 0;
|
pace_input.pin_length = 0;
|
||||||
}
|
}
|
||||||
t_start = time(NULL);
|
t_start = time(NULL);
|
||||||
i = EstablishPACEChannel(NULL, card, pace_input, &out, &outlen,
|
i = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
|
||||||
&sctx);
|
&sctx);
|
||||||
t_end = time(NULL);
|
t_end = time(NULL);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
@@ -419,7 +419,7 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
t_start = time(NULL);
|
t_start = time(NULL);
|
||||||
i = EstablishPACEChannel(NULL, card, pace_input, &out, &outlen,
|
i = EstablishPACEChannel(NULL, card, pace_input, &pace_output,
|
||||||
&sctx);
|
&sctx);
|
||||||
t_end = time(NULL);
|
t_end = time(NULL);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
@@ -435,8 +435,6 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (channeldata)
|
|
||||||
free(channeldata);
|
|
||||||
sc_disconnect_card(card, 0);
|
sc_disconnect_card(card, 0);
|
||||||
sc_release_context(ctx);
|
sc_release_context(ctx);
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include "pace.h"
|
#include "pace.h"
|
||||||
#include "sm.h"
|
#include "sm.h"
|
||||||
#include "scutil.h"
|
#include "scutil.h"
|
||||||
#include <asm/byteorder.h>
|
|
||||||
#include <opensc/asn1.h>
|
#include <opensc/asn1.h>
|
||||||
#include <opensc/log.h>
|
#include <opensc/log.h>
|
||||||
#include <opensc/opensc.h>
|
#include <opensc/opensc.h>
|
||||||
@@ -160,29 +159,20 @@ IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_R)
|
|||||||
|
|
||||||
const size_t maxresp = SC_MAX_APDU_BUFFER_SIZE - 2;
|
const size_t maxresp = SC_MAX_APDU_BUFFER_SIZE - 2;
|
||||||
|
|
||||||
int GetReadersPACECapabilities(sc_card_t *card,
|
int GetReadersPACECapabilities(u8 *bitmap)
|
||||||
const __u8 *in, size_t inlen, __u8 **out, size_t *outlen) {
|
{
|
||||||
if (!out || !outlen)
|
if (!bitmap)
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
__u8 *result = realloc(*out, 2);
|
|
||||||
if (!result)
|
|
||||||
return SC_ERROR_OUT_OF_MEMORY;
|
|
||||||
*out = result;
|
|
||||||
*outlen = 2;
|
|
||||||
|
|
||||||
/* lengthBitMap */
|
|
||||||
*result = 1;
|
|
||||||
result++;
|
|
||||||
/* BitMap */
|
/* BitMap */
|
||||||
*result = PACE_BITMAP_PACE|PACE_BITMAP_EID;
|
*bitmap = PACE_BITMAP_PACE|PACE_BITMAP_EID;
|
||||||
|
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** select and read EF.CardAccess */
|
/** select and read EF.CardAccess */
|
||||||
static int get_ef_card_access(sc_card_t *card,
|
static int get_ef_card_access(sc_card_t *card,
|
||||||
__u8 **ef_cardaccess, size_t *length_ef_cardaccess)
|
u8 **ef_cardaccess, size_t *length_ef_cardaccess)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
/* we read less bytes than possible. this is a workaround for acr 122,
|
/* we read less bytes than possible. this is a workaround for acr 122,
|
||||||
@@ -190,7 +180,7 @@ static int get_ef_card_access(sc_card_t *card,
|
|||||||
size_t read = maxresp - 8;
|
size_t read = maxresp - 8;
|
||||||
sc_path_t path;
|
sc_path_t path;
|
||||||
sc_file_t *file = NULL;
|
sc_file_t *file = NULL;
|
||||||
__u8 *p;
|
u8 *p;
|
||||||
|
|
||||||
memset(&path, 0, sizeof path);
|
memset(&path, 0, sizeof path);
|
||||||
r = sc_append_file_id(&path, FID_EF_CARDACCESS);
|
r = sc_append_file_id(&path, FID_EF_CARDACCESS);
|
||||||
@@ -959,10 +949,10 @@ void ssl_error(sc_context_t *ctx) {
|
|||||||
|
|
||||||
int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
||||||
struct establish_pace_channel_input pace_input,
|
struct establish_pace_channel_input pace_input,
|
||||||
__u8 **out, size_t *outlen, struct sm_ctx *sctx)
|
struct establish_pace_channel_output *pace_output,
|
||||||
|
struct sm_ctx *sctx)
|
||||||
{
|
{
|
||||||
size_t length_ef_cardaccess, recent_car_len, prev_car_len;
|
u8 *p = NULL;
|
||||||
__u8 *ef_cardaccess = NULL, *p = NULL, *recent_car = NULL, *prev_car = NULL;
|
|
||||||
PACEInfo *info = NULL;
|
PACEInfo *info = NULL;
|
||||||
PACEDomainParameterInfo *static_dp = NULL, *eph_dp = NULL;
|
PACEDomainParameterInfo *static_dp = NULL, *eph_dp = NULL;
|
||||||
BUF_MEM *enc_nonce = NULL, *nonce = NULL, *mdata = NULL, *mdata_opp = NULL,
|
BUF_MEM *enc_nonce = NULL, *nonce = NULL, *mdata = NULL, *mdata_opp = NULL,
|
||||||
@@ -971,42 +961,25 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
|||||||
PACE_SEC *sec = NULL;
|
PACE_SEC *sec = NULL;
|
||||||
PACE_CTX *pctx = NULL;
|
PACE_CTX *pctx = NULL;
|
||||||
int r;
|
int r;
|
||||||
__le16 word;
|
|
||||||
|
|
||||||
if (!card)
|
if (!card)
|
||||||
return SC_ERROR_CARD_NOT_PRESENT;
|
return SC_ERROR_CARD_NOT_PRESENT;
|
||||||
if (!out || !outlen)
|
if (!pace_output || !sctx)
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (!oldpacectx) {
|
if (!pace_output->ef_cardaccess_length || !pace_output->ef_cardaccess) {
|
||||||
/* PACE is executed the first time */
|
r = get_ef_card_access(card, &pace_output->ef_cardaccess,
|
||||||
r = get_ef_card_access(card, &ef_cardaccess, &length_ef_cardaccess);
|
&pace_output->ef_cardaccess_length);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(card->ctx, "Could not get EF.CardAccess.");
|
sc_error(card->ctx, "Could not get EF.CardAccess.");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
/* get enough memory for status bytes and EF.CardAccess */
|
|
||||||
p = realloc(*out, 6 + length_ef_cardaccess);
|
|
||||||
if (!p) {
|
|
||||||
r = SC_ERROR_OUT_OF_MEMORY;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
*out = p;
|
|
||||||
word = __cpu_to_le16(length_ef_cardaccess);
|
|
||||||
memcpy((*out) + 2, &word, sizeof word);
|
|
||||||
memcpy((*out) + 4, ef_cardaccess, length_ef_cardaccess);
|
|
||||||
} else {
|
|
||||||
/* PACE is executed the second time. EF.CardAccess should already be
|
|
||||||
* present */
|
|
||||||
memcpy(&word, (*out) + 2, sizeof word);
|
|
||||||
length_ef_cardaccess = __le16_to_cpu(word);
|
|
||||||
ef_cardaccess = (*out) + 4;
|
|
||||||
}
|
}
|
||||||
*outlen = 4+length_ef_cardaccess;
|
bin_log(card->ctx, "EF.CardAccess", pace_output->ef_cardaccess,
|
||||||
bin_log(card->ctx, "EF.CardAccess", ef_cardaccess, length_ef_cardaccess);
|
pace_output->ef_cardaccess_length);
|
||||||
|
|
||||||
if (!parse_ef_card_access(ef_cardaccess, length_ef_cardaccess,
|
if (!parse_ef_card_access(pace_output->ef_cardaccess,
|
||||||
&info, &static_dp)) {
|
pace_output->ef_cardaccess_length, &info, &static_dp)) {
|
||||||
sc_error(card->ctx, "Could not parse EF.CardAccess.");
|
sc_error(card->ctx, "Could not parse EF.CardAccess.");
|
||||||
ssl_error(card->ctx);
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
@@ -1014,7 +987,8 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
|||||||
}
|
}
|
||||||
|
|
||||||
r = pace_mse_set_at(oldpacectx, card, info->protocol, pace_input.pin_id,
|
r = pace_mse_set_at(oldpacectx, card, info->protocol, pace_input.pin_id,
|
||||||
pace_input.chat, pace_input.chat_length, *out, (*out)+1);
|
pace_input.chat, pace_input.chat_length,
|
||||||
|
&pace_output->mse_set_at_sw1, &pace_output->mse_set_at_sw2);
|
||||||
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).");
|
||||||
@@ -1112,23 +1086,9 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
r = pace_gen_auth_4_mutual_authentication(oldpacectx, card, (u8 *) token->data, token->length,
|
r = pace_gen_auth_4_mutual_authentication(oldpacectx, card, (u8 *) token->data, token->length,
|
||||||
(u8 **) &token_opp->data, &token_opp->length, &recent_car, &recent_car_len,
|
(u8 **) &token_opp->data, &token_opp->length,
|
||||||
&prev_car, &prev_car_len);
|
&pace_output->recent_car, &pace_output->recent_car_length,
|
||||||
|
&pace_output->previous_car, &pace_output->previous_car_length);
|
||||||
/* get enough memory for CARs */
|
|
||||||
p = realloc(*out, (*outlen) + 1 + recent_car_len + 1 + prev_car_len);
|
|
||||||
if (!p) {
|
|
||||||
r = SC_ERROR_OUT_OF_MEMORY;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
*out = p;
|
|
||||||
(*out)[*outlen] = recent_car_len;
|
|
||||||
memcpy((*out) + (*outlen) + 1,
|
|
||||||
recent_car, recent_car_len);
|
|
||||||
(*out)[(*outlen) + 1 + recent_car_len] = prev_car_len;
|
|
||||||
memcpy((*out) + (*outlen) + 1 + recent_car_len + 1,
|
|
||||||
prev_car, prev_car_len);
|
|
||||||
*outlen += 1 + recent_car_len + 1 + prev_car_len;
|
|
||||||
|
|
||||||
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 "
|
||||||
@@ -1145,15 +1105,7 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get enough memory for IDicc */
|
/* XXX IDicc */
|
||||||
p = realloc(*out, (*outlen) + 2);
|
|
||||||
if (!p) {
|
|
||||||
r = SC_ERROR_OUT_OF_MEMORY;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
*out = p;
|
|
||||||
memset((*out) + (*outlen), 0, 2);
|
|
||||||
*outlen += 2;
|
|
||||||
|
|
||||||
/* XXX parse CHAT to check role of terminal */
|
/* XXX parse CHAT to check role of terminal */
|
||||||
|
|
||||||
@@ -1178,8 +1130,6 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
|||||||
sctx->active = 1;
|
sctx->active = 1;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (ef_cardaccess && !oldpacectx)
|
|
||||||
free(ef_cardaccess);
|
|
||||||
if (info)
|
if (info)
|
||||||
PACEInfo_free(info);
|
PACEInfo_free(info);
|
||||||
if (static_dp)
|
if (static_dp)
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
#include "pace_lib.h"
|
#include "pace_lib.h"
|
||||||
#include "sm.h"
|
#include "sm.h"
|
||||||
#include <linux/usb/ch9.h>
|
|
||||||
#include <opensc/opensc.h>
|
#include <opensc/opensc.h>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/pace.h>
|
#include <openssl/pace.h>
|
||||||
@@ -97,11 +96,12 @@ struct establish_pace_channel_output {
|
|||||||
unsigned char *id_icc;
|
unsigned char *id_icc;
|
||||||
};
|
};
|
||||||
|
|
||||||
int GetReadersPACECapabilities(sc_card_t *card, const unsigned char *in,
|
int GetReadersPACECapabilities(u8 *bitmap);
|
||||||
size_t inlen, unsigned char **out, size_t *outlen);
|
|
||||||
int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
||||||
struct establish_pace_channel_input pace_input,
|
struct establish_pace_channel_input pace_input,
|
||||||
unsigned char **out, size_t *outlen, struct sm_ctx *sctx);
|
struct establish_pace_channel_output *pace_output,
|
||||||
|
struct sm_ctx *sctx);
|
||||||
|
|
||||||
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, int ask_for_secret,
|
enum s_type pin_id, int ask_for_secret,
|
||||||
|
|||||||
Reference in New Issue
Block a user