Skip to content

Commit

Permalink
dtrust card: implemented PACE verification
Browse files Browse the repository at this point in the history
  • Loading branch information
frankmorgner committed May 14, 2024
1 parent ad4dbdd commit 80349e2
Showing 1 changed file with 83 additions and 0 deletions.
83 changes: 83 additions & 0 deletions src/libopensc/card-dtrust.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include "asn1.h"
#include "internal.h"
#include "sm/sm-eac.h"

static const struct sc_card_operations *iso_ops = NULL;

Expand Down Expand Up @@ -468,6 +469,87 @@ dtrust_compute_signature(struct sc_card *card, const u8 *data,
return r;
}

static int
_dtrust_pace_verify(sc_card_t *card, u8 pin_reference, const u8 *pin, size_t pin_length, int *tries_left)
{
int r;
struct establish_pace_channel_input pace_input;
struct establish_pace_channel_output pace_output;

memset(&pace_input, 0, sizeof pace_input);
memset(&pace_output, 0, sizeof pace_output);

pace_input.pin_id = pin_reference;
pace_input.pin = pin;
pace_input.pin_length = pin_length;
r = perform_pace(card, pace_input, &pace_output, EAC_TR_VERSION_2_02);

if (tries_left) {
if (pace_output.mse_set_at_sw1 == 0x90 && pace_output.mse_set_at_sw2 == 0x00)
*tries_left = 3;
if (pace_output.mse_set_at_sw1 == 0x69 && pace_output.mse_set_at_sw2 == 0x83)
*tries_left = 0;
if (pace_output.mse_set_at_sw1 == 0x63 && (pace_output.mse_set_at_sw2 & 0xC0) == 0xC0)
*tries_left = pace_output.mse_set_at_sw2 & 0x0F;
}
free(pace_output.ef_cardaccess);
free(pace_output.recent_car);
free(pace_output.previous_car);
free(pace_output.id_icc);
free(pace_output.id_pcd);

return r;
}

#ifndef CAN
#define CAN "123456"
#endif

static int
_dtrust_verify_can(sc_card_t *card)
{
return _dtrust_pace_verify(card, 0x02, (u8 *)CAN, strlen(CAN), NULL);
}

static int
dtrust_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left)
{
int r;

if (card->type == SC_CARD_TYPE_DTRUST_V5_1_STD && data->cmd == SC_PIN_CMD_VERIFY) {
switch (data->pin_reference) {
/* <id> = '04' for PUK.CH
<id> = '91' for PIN.AUT */
case 0x87:
/* PIN.QES */
case 0x91:
/* PIN.AUT */

/* verification requires SM channel with PACE+CAN */
if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT) {
/* assume that CAN has previously been verified if SM is active. */
r = _dtrust_verify_can(card);
LOG_TEST_RET(card->ctx, r, "Error verifying CAN.");
}
break;

case 0x0B:
/* PIN.T */
case 0x0C:
/* PIN.T.AUT */
case 0x04:
/* PUK.CH */

/* verification is done with PACE+<id> */
return _dtrust_pace_verify(card, data->pin_reference, data->pin1.data, data->pin1.len, tries_left);
}
}

r = iso_ops->pin_cmd(card, data, tries_left);

return r;
}

static int
dtrust_logout(sc_card_t *card)
{
Expand All @@ -492,6 +574,7 @@ sc_get_dtrust_driver(void)
dtrust_ops.finish = dtrust_finish;
dtrust_ops.set_security_env = dtrust_set_security_env;
dtrust_ops.compute_signature = dtrust_compute_signature;
dtrust_ops.pin_cmd = dtrust_pin_cmd,
dtrust_ops.logout = dtrust_logout;

return &dtrust_drv;
Expand Down

0 comments on commit 80349e2

Please sign in to comment.