added verification of age/validity/community

This commit is contained in:
Frank Morgner
2013-01-31 23:47:48 +01:00
parent 9f6ffc2fad
commit d98f4e57c9
4 changed files with 164 additions and 11 deletions

View File

@@ -21,10 +21,10 @@
#endif
#include "cmdline.h"
#include "config.h"
#include <eac/pace.h>
#include <libopensc/log.h>
#include <libopensc/opensc.h>
#include <npa/iso-sm.h>
#include <npa/npa.h>
#include <npa/scutil.h>
#include <stdint.h>
@@ -109,16 +109,39 @@ static void write_dg(sc_card_t *card, unsigned char sfid, const char *dg_str,
r = sc_hex_to_bin(dg_hex, dg, &dg_len);
if (r < 0) {
fprintf(stderr, "Coult not parse DG %02u %s (%s)\n",
fprintf(stderr, "Could not parse DG %02u %s (%s)\n",
sfid, dg_str, sc_strerror(r));
} else {
r = write_binary_rec(card, sfid, dg, dg_len);
if (r < 0)
printf("Coult not write DG %02u %s (%s)\n",
fprintf(stderr, "Could not write DG %02u %s (%s)\n",
sfid, dg_str, sc_strerror(r));
else
printf("Wrote DG %02u %s\n", sfid, dg_str);
}
}
#define ISO_VERIFY 0x20
static void verify(sc_card_t *card, const char *verify_str,
const unsigned char *data, size_t data_len)
{
sc_apdu_t apdu;
int r;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, ISO_VERIFY, 0x80, 0);
apdu.cla = 0x80;
apdu.data = data;
apdu.datalen = data_len;
apdu.lc = data_len;
r = sc_transmit_apdu(card, &apdu);
if (r < 0)
fprintf(stderr, "Coult not verify %s (%s)\n",
verify_str, sc_strerror(r));
else
printf("Verified %s\n", verify_str);
}
int npa_translate_apdus(sc_card_t *card, FILE *input)
{
u8 buf[4 + 3 + 0xffff + 3];
@@ -184,6 +207,65 @@ int npa_translate_apdus(sc_card_t *card, FILE *input)
return r;
}
static int add_to_CVC_DISCRETIONARY_DATA_TEMPLATES(
CVC_DISCRETIONARY_DATA_TEMPLATES **templates,
int nid, const unsigned char *data, size_t data_len)
{
int r;
CVC_DISCRETIONARY_DATA_TEMPLATE **template;
if (!templates) {
r = SC_ERROR_INVALID_ARGUMENTS;
goto err;
}
if (!*templates) {
*templates = CVC_DISCRETIONARY_DATA_TEMPLATES_new();
if (!*templates) {
r = SC_ERROR_INTERNAL;
goto err;
}
}
if (!(*templates)->template1)
template = &(*templates)->template1;
else if (!(*templates)->template2)
template = &(*templates)->template2;
else {
fprintf(stderr,
"Not enough space in auxiliary data for that many data templates");
r = SC_ERROR_INVALID_ARGUMENTS;
goto err;
}
*template = CVC_DISCRETIONARY_DATA_TEMPLATE_new();
if (!*template) {
r = SC_ERROR_INTERNAL;
goto err;
}
(*template)->type = OBJ_nid2obj(nid);
if (!(*template)->type) {
r = SC_ERROR_INTERNAL;
goto err;
}
if (data && data_len) {
(*template)->discretionary_data1 = ASN1_OCTET_STRING_new();
if (!(*template)->discretionary_data1
|| !M_ASN1_OCTET_STRING_set(
(*template)->discretionary_data1, data, data_len)) {
r = SC_ERROR_INTERNAL;
goto err;
}
}
r = SC_SUCCESS;
err:
return r;
}
int
main (int argc, char **argv)
{
@@ -201,14 +283,18 @@ main (int argc, char **argv)
size_t privkey_len = 0;
unsigned char auxiliary_data[0xff];
size_t auxiliary_data_len = 0;
unsigned char new_dg[0xff];
size_t new_dg_len;
unsigned char *verify_age_data = NULL;
size_t verify_age_len = 0;
unsigned char *verify_community_data = NULL;
size_t verify_community_len = 0;
unsigned char *verify_validity_data = NULL;
size_t verify_validity_len = 0;
sc_context_t *ctx = NULL;
sc_card_t *card = NULL;
sc_reader_t *reader;
int r, oindex = 0, tr_version = EAC_TR_VERSION_2_02;
int r, tr_version = EAC_TR_VERSION_2_02;
struct establish_pace_channel_input pace_input;
struct establish_pace_channel_output pace_output;
struct timeval tv;
@@ -218,6 +304,7 @@ main (int argc, char **argv)
unsigned char *certs_chat = NULL;
unsigned char *dg = NULL;
size_t dg_len = 0;
CVC_DISCRETIONARY_DATA_TEMPLATES *templates = NULL;
struct gengetopt_args_info cmdline;
@@ -494,6 +581,44 @@ main (int argc, char **argv)
fprintf(stderr, "Could not parse auxiliary data.\n");
exit(2);
}
} else {
if (cmdline.older_than_given) {
r = add_to_CVC_DISCRETIONARY_DATA_TEMPLATES(&templates,
NID_id_DateOfBirth, cmdline.older_than_arg,
strlen(cmdline.older_than_arg));
if (r < 0) {
fprintf(stderr, "Error formatting age verification data template.\n");
goto err;
}
}
if (cmdline.verify_validity_given) {
r = add_to_CVC_DISCRETIONARY_DATA_TEMPLATES(&templates,
NID_id_DateOfExpiry, NULL, 0);
if (r < 0) {
fprintf(stderr, "Error formatting validity verification data template.\n");
goto err;
}
}
if (cmdline.verify_community_given) {
r = add_to_CVC_DISCRETIONARY_DATA_TEMPLATES(&templates,
NID_id_CommunityID, cmdline.verify_community_arg,
strlen(cmdline.verify_community_arg));
if (r < 0) {
fprintf(stderr, "Error formatting community ID verification data template.\n");
goto err;
}
}
unsigned char *p = NULL;
auxiliary_data_len = i2d_CVC_DISCRETIONARY_DATA_TEMPLATES(
templates, &p);
if (0 >= (int) auxiliary_data_len
|| auxiliary_data_len > sizeof auxiliary_data) {
free(p);
r = SC_ERROR_INTERNAL;
goto err;
}
memcpy(auxiliary_data, p, auxiliary_data_len);
free(p);
}
}
@@ -611,6 +736,19 @@ main (int argc, char **argv)
if (cmdline.write_dg21_given)
write_dg(card, 21, "Optional Data", cmdline.write_dg21_arg);
if (cmdline.older_than_given) {
unsigned char id_DateOfBirth[] = {6, 9, 4, 0, 127, 0, 7, 3, 1, 4, 1};
verify(card, "age", id_DateOfBirth, sizeof id_DateOfBirth);
}
if (cmdline.verify_validity_given) {
unsigned char id_DateOfExpiry[] = {6, 9, 4, 0, 127, 0, 7, 3, 1, 4, 2};
verify(card, "validity", id_DateOfExpiry, sizeof id_DateOfExpiry);
}
if (cmdline.verify_community_given) {
unsigned char id_CommunityID[] = {6, 9, 4, 0, 127, 0, 7, 3, 1, 4, 3};
verify(card, "community ID", id_CommunityID, sizeof id_CommunityID);
}
if (cmdline.translate_given) {
if (strncmp(cmdline.translate_arg, "stdin", strlen("stdin")) == 0)
input = stdin;
@@ -652,6 +790,8 @@ err:
if (cvc_cert)
CVC_CERT_free(cvc_cert);
free(dg);
if (templates)
CVC_DISCRETIONARY_DATA_TEMPLATES_free(templates);
sm_stop(card);
sc_reset(card, 1);

View File

@@ -57,7 +57,7 @@ option "chat" -
typestr="HEX_STRING"
optional
option "auxiliary-data" A
"Terminal's auxiliary data."
"Terminal's auxiliary data (default is determined by age verification and community id verification)."
string
typestr="HEX_STRING"
optional
@@ -169,6 +169,20 @@ option "write-dg21" -
typestr="HEX_STRING"
optional
section "nPA operations"
option "older-than" -
"Verify age with a reference date"
string
typestr="YYYYMMDD"
optional
option "verify-validity" -
"Verify document validity with the chips current date"
flag off
option "verify-community" -
"Verify community ID with a reference ID"
string
optional
section "Special options, not always useful"
option "break" b
"Brute force PIN, CAN or PUK"

View File

@@ -43,7 +43,6 @@
#define ASN1_APP_IMP_OPT(stname, field, type, tag) ASN1_EX_TYPE(ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION|ASN1_TFLG_OPTIONAL, tag, stname, field, type)
#define ASN1_APP_IMP(stname, field, type, tag) ASN1_EX_TYPE(ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION, tag, stname, field, type)
IMPLEMENT_ASN1_FUNCTIONS(CVC_DISCRETIONARY_DATA_TEMPLATES)
/*
* MSE:Set AT
@@ -321,7 +320,6 @@ int read_binary_rec(sc_card_t *card, unsigned char sfid,
size_t read = maxresp - 8;
sc_apdu_t apdu;
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;
@@ -514,6 +512,7 @@ static int format_mse_cdata(struct sc_context *ctx, int protocol,
}
if (auxiliary_data && auxiliary_data_len) {
bin_log(ctx, SC_LOG_DEBUG_NORMAL, "test", auxiliary_data, auxiliary_data_len);
if (!d2i_CVC_DISCRETIONARY_DATA_TEMPLATES(&data->auxiliary_data, &auxiliary_data, auxiliary_data_len)) {
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Error setting auxiliary authenticated data of MSE:Set AT data");
r = SC_ERROR_INTERNAL;
@@ -2131,7 +2130,6 @@ npa_sm_verify_authentication(sc_card_t *card, const struct iso_sm_ctx *ctx,
const u8 *macdata, size_t macdatalen)
{
int r;
char *p;
BUF_MEM *inbuf = NULL, *my_mac = NULL;
if (!card || !ctx || !ctx->priv_data) {

View File

@@ -155,7 +155,8 @@ int perform_pace(sc_card_t *card,
* @param[in] privkey The terminal's private key
* @param[in] privkey_len length of \a privkey
* @param[in] auxiliary_data auxiliary data for age/validity/community ID
* verification
* verification. Should be formatted as buffer of
* \c CVC_DISCRETIONARY_DATA_TEMPLATES
* @param[in] auxiliary_data_len length of \a auxiliary_data
*
* @return \c SC_SUCCESS or error code if an error occurred