Added support for Password Authenticated Connection Establishment (PACE) using

OpenPACE (http://sourceforge.net/projects/openpace/). Since it is currently
untested, it is disabled by default.


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@40 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2010-02-28 18:58:35 +00:00
parent 0a06537cee
commit 4900d205ce
6 changed files with 769 additions and 5 deletions

View File

@@ -2,8 +2,12 @@ Installation is simple; type `make install`. If you want to customize the
compilation or install process, you will need to pass variables to make.
DESTDIR prefix for installation
LIBPCSCLITE_CFLAGS compiler flags for pcsclite usage (needed if no
OPENSC_CFLAGS compiler flags for libopensc usage (needed if no
pkg-config is available)
OPENSSL_CFLAGS compiler flags for libssl usage (needed if no
pkg-config is available)
EXTRA_CFLAGS set it to "" to enable PACE, make sure that your
openssl is compiled with the OpenPACE patch
See the Makefile for more details.

View File

@@ -8,9 +8,10 @@ bindir = $(exec_prefix)/bin
# Compiler
CC = gcc
CFLAGS = -Wall -g
CFLAGS = -Wall -g
EXTRA_CFLAGS = -DNO_PACE
#LIBPCSCLITE_CFLAGS = `pkg-config --cflags --libs libpcsclite`
#OPENSSL_CFLAGS = `pkg-config --cflags --libs libssl`
OPENSSL_CFLAGS = `pkg-config --cflags --libs libssl`
OPENSC_CFLAGS = `pkg-config --cflags --libs libopensc`
PTHREAD_CFLAGS = -pthread
@@ -24,8 +25,10 @@ TARGETS = ccid
all: $(TARGETS)
ccid: ccid.h ccid.c usbstring.c usbstring.h usb.c
$(CC) $(LIBPCSCLITE_CFLAGS) $(OPENSC_CFLAGS) $(OPENSSL_CFLAGS) $(PTHREAD_CFLAGS) $(CFLAGS) usbstring.c ccid.c usb.c -o $@
ccid: ccid.h ccid.c pace.h pace.c usbstring.c usbstring.h usb.c
$(CC) $(LIBPCSCLITE_CFLAGS) $(OPENSC_CFLAGS) $(OPENSSL_CFLAGS) \
$(PTHREAD_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) \
usbstring.c ccid.c pace.c usb.c -o $@
install: $(TARGETS) installdirs

View File

@@ -9,6 +9,10 @@ as a standard USB CCID reader. If the host system is in USB device mode, ccid
forwards the local reader via USB to an other device. If in USB host mode,
ccid virtually plugges in a USB CCID reader to the host system.
ccid has support for Password Authenticated Connection Establishment (PACE)
using OpenPACE (see http://sourceforge.net/projects/openpace/). PACE is
experimental and disabled by default. See file INSTALL how to compile it.
ccid is implemented using GadgetFS. The source code is based on the GadgetFS
example at http://www.linux-usb.org/gadget/.

View File

@@ -1,3 +1,21 @@
/*
* Copyright (C) 2009 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 <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdarg.h>
#include <string.h>

583
ccid/pace.c Normal file
View File

@@ -0,0 +1,583 @@
/*
* Copyright (C) 2010 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 <http://www.gnu.org/licenses/>.
*/
#include <opensc/log.h>
#include "pace.h"
#ifdef NO_PACE
inline int GetReadersPACECapabilities(sc_context_t *ctx, sc_card_t *card,
const __u8 *in, __u8 **out, size_t *outlen) {
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_NOT_SUPPORTED);
}
inline int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card,
const __u8 *in, __u8 **out, size_t *outlen) {
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_NOT_SUPPORTED);
}
#else
#include <opensc/opensc.h>
#include <opensc/ui.h>
#include <openssl/pace.h>
#include <openssl/objects.h>
#include <openssl/err.h>
#include <asm/byteorder.h>
#include <string.h>
uint16_t ssc = 0;
int GetReadersPACECapabilities(sc_context_t *ctx, sc_card_t *card,
const __u8 *in, __u8 **out, size_t *outlen) {
if (!out || !outlen)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
__u8 *result = realloc(*out, 2);
if (!result)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
*out = result;
*outlen = 2;
/* lengthBitMap */
*result = 1;
result++;
/* BitMap */
*result = PACE_BITMAP_PACE|PACE_BITMAP_EID;
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
}
/** select and read EF.CardAccess */
int get_ef_card_access(sc_context_t *ctx, sc_card_t *card,
__u8 **ef_cardaccess, size_t *length_ef_cardaccess)
{
int r;
char buf[9];
sc_path_t path;
sc_file_t *file;
snprintf(buf, sizeof buf, "3f00%04x", FID_EF_CARDACCESS);
sc_format_path(buf, &path);
SC_TEST_RET(ctx, sc_select_file(card, &path, &file),
"Could not select EF.CardAccess.");
ssc++;
*length_ef_cardaccess = file->size;
*ef_cardaccess = malloc(*length_ef_cardaccess);
if (!*ef_cardaccess)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
r = sc_read_binary(card, 0, *ef_cardaccess, *length_ef_cardaccess, 0);
ssc++;
SC_TEST_RET(ctx, r, "Could not read EF.CardAccess.");
*length_ef_cardaccess = r;
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
}
int pace_mse_set_at(sc_context_t *ctx, sc_card_t *card,
int protocol, int secret_key, int reference)
{
sc_apdu_t apdu;
unsigned char *d = NULL;
PACE_MSE_SET_AT_C *data = NULL;
int r;
memset(&apdu, 0, sizeof apdu);
apdu.ins = 0x22;
apdu.p1 = 0xc1;
apdu.p2 = 0xa4;
apdu.flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL;
data = PACE_MSE_SET_AT_C_new();
if (!data) {
r = SC_ERROR_OUT_OF_MEMORY;
goto err;
}
data->cryptographic_mechanism_reference = OBJ_nid2obj(protocol);
data->key_reference1 = ASN1_INTEGER_new();
data->key_reference2 = ASN1_INTEGER_new();
if (!data->cryptographic_mechanism_reference
|| !data->key_reference1
|| !data->key_reference2) {
r = SC_ERROR_OUT_OF_MEMORY;
goto err;
}
if (!ASN1_INTEGER_set(data->key_reference1, secret_key)
|| !ASN1_INTEGER_set(data->key_reference2, reference)) {
r = SC_ERROR_INTERNAL;
goto err;
}
r = i2d_PACE_MSE_SET_AT_C(data, &d);
if (r < 0) {
r = SC_ERROR_INTERNAL;
goto err;
}
apdu.data = (const u8 *) d;
apdu.datalen = r;
apdu.lc = r;
r = sc_transmit_apdu(card, &apdu);
ssc++;
if (r < 0)
goto err;
if (apdu.resplen) {
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err;
}
if (apdu.sw1 == 0x63) {
if ((apdu.sw2 & 0xc0) == 0xc0) {
sc_error(card->ctx, "Verification failed (remaining tries: %d%s)\n",
apdu.sw2 & 0x0f,
(apdu.sw2 & 0x0f) == 1? ", password must be resumed":
(apdu.sw2 & 0x0f) == 0? ", password must be unblocked":
"");
r = SC_ERROR_PIN_CODE_INCORRECT;
goto err;
} else {
sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n",
apdu.sw1, apdu.sw2);
r = SC_ERROR_CARD_CMD_FAILED;
goto err;
}
} else if (apdu.sw1 == 0x62 && apdu.sw2 == 0x83) {
sc_error(card->ctx, "Password is deactivated\n");
r = SC_ERROR_AUTH_METHOD_BLOCKED;
goto err;
} else {
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
}
err:
if (data) {
if (data->cryptographic_mechanism_reference)
ASN1_OBJECT_free(data->cryptographic_mechanism_reference);
if (data->key_reference1)
ASN1_INTEGER_free(data->key_reference1);
if (data->key_reference2)
ASN1_INTEGER_free(data->key_reference2);
PACE_MSE_SET_AT_C_free(data);
}
if (d)
free(d);
if (apdu.resplen)
free(apdu.resp);
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, r);
}
int pace_gen_auth(sc_context_t *ctx, sc_card_t *card,
int step, const u8 *in, size_t in_len, u8 **out, size_t *out_len)
{
sc_apdu_t apdu;
PACE_GEN_AUTH_C *c_data = NULL;
PACE_GEN_AUTH_R *r_data = NULL;
unsigned char *d = NULL, *p;
int r, l;
memset(&apdu, 0, sizeof apdu);
apdu.ins = 0x86;
apdu.p1 = 0;
apdu.p2 = 0;
apdu.flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL;
c_data = PACE_GEN_AUTH_C_new();
if (!c_data) {
r = SC_ERROR_OUT_OF_MEMORY;
goto err;
}
switch(step) {
case 1:
break;
case 2:
c_data->mapping_data = ASN1_OCTET_STRING_new();
if (!c_data->mapping_data
|| !M_ASN1_OCTET_STRING_set(
c_data->mapping_data, in, in_len)) {
r = SC_ERROR_INTERNAL;
goto err;
}
break;
case 3:
c_data->eph_pub_key = ASN1_OCTET_STRING_new();
if (!c_data->eph_pub_key
|| !M_ASN1_OCTET_STRING_set(
c_data->eph_pub_key, in, in_len)) {
r = SC_ERROR_INTERNAL;
goto err;
}
break;
case 4:
c_data->auth_token = ASN1_OCTET_STRING_new();
if (!c_data->auth_token
|| !M_ASN1_OCTET_STRING_set(
c_data->auth_token, in, in_len)) {
r = SC_ERROR_INTERNAL;
goto err;
}
break;
default:
r = SC_ERROR_INVALID_ARGUMENTS;
goto err;
}
r = i2d_PACE_GEN_AUTH_C(c_data, &d);
if (r < 0) {
r = SC_ERROR_INTERNAL;
goto err;
}
apdu.data = (const u8 *) d;
apdu.datalen = r;
apdu.lc = r;
r = sc_transmit_apdu(card, &apdu);
ssc++;
if (r < 0)
goto err;
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r < 0)
goto err;
if (!d2i_PACE_GEN_AUTH_R(&r_data,
(const unsigned char **) &apdu.resp, apdu.resplen)) {
r = SC_ERROR_INTERNAL;
goto err;
}
switch(step) {
case 1:
if (!r_data->enc_nonce
|| r_data->mapping_data
|| r_data->eph_pub_key
|| r_data->auth_token) {
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err;
}
p = r_data->enc_nonce->data;
l = r_data->enc_nonce->length;
break;
case 2:
if (r_data->enc_nonce
|| !r_data->mapping_data
|| r_data->eph_pub_key
|| r_data->auth_token) {
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err;
}
p = r_data->mapping_data->data;
l = r_data->mapping_data->length;
break;
case 3:
if (r_data->enc_nonce
|| r_data->mapping_data
|| !r_data->eph_pub_key
|| r_data->auth_token) {
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err;
}
p = r_data->eph_pub_key->data;
l = r_data->eph_pub_key->length;
break;
case 4:
if (r_data->enc_nonce
|| r_data->mapping_data
|| r_data->eph_pub_key
|| !r_data->auth_token) {
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err;
}
p = r_data->auth_token->data;
l = r_data->auth_token->length;
break;
default:
r = SC_ERROR_INVALID_ARGUMENTS;
goto err;
}
*out = malloc(l);
if (!*out) {
r = SC_ERROR_OUT_OF_MEMORY;
goto err;
}
memcpy(p, *out, l);
*out_len = l;
err:
if (c_data) {
if (c_data->mapping_data)
ASN1_OCTET_STRING_free(c_data->mapping_data);
if (c_data->eph_pub_key)
ASN1_OCTET_STRING_free(c_data->eph_pub_key);
if (c_data->auth_token)
ASN1_OCTET_STRING_free(c_data->auth_token);
PACE_GEN_AUTH_C_free(c_data);
}
if (d)
free(d);
if (r_data) {
if (r_data->mapping_data)
ASN1_OCTET_STRING_free(r_data->mapping_data);
if (r_data->eph_pub_key)
ASN1_OCTET_STRING_free(r_data->eph_pub_key);
if (r_data->auth_token)
ASN1_OCTET_STRING_free(r_data->auth_token);
PACE_GEN_AUTH_R_free(r_data);
}
if (apdu.resplen)
free(apdu.resp);
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, r);
}
PACE_SEC *
get_psec(sc_card_t *card, const char *pin, size_t length_pin, u8 pin_id)
{
sc_ui_hints_t hints;
char *p;
PACE_SEC *r;
int sc_result;
if (pin && length_pin)
return PACE_SEC_new(pin, length_pin, pin_id);
memset(&hints, 0, sizeof(hints));
hints.dialog_name = "ccid.PACE";
hints.card = card;
switch(pin_id) {
case PACE_MRZ:
hints.prompt = "Enter MRZ";
break;
case PACE_CAN:
hints.prompt = "Enter CAN";
break;
case PACE_PIN:
hints.prompt = "Enter PIN";
break;
case PACE_PUK:
hints.prompt = "Enter PUK";
break;
default:
return NULL;
}
hints.usage = SC_UI_USAGE_OTHER;
sc_result = sc_ui_get_pin(&hints, &p);
if (sc_result < 0) {
sc_error(card->ctx, "Could not read PACE secret (%s).\n",
sc_strerror(sc_result));
return NULL;
}
r = PACE_SEC_new(p, strlen(p), pin_id);
OPENSSL_cleanse(p, strlen(p));
free(p);
return r;
}
void debug_ossl(sc_context_t *ctx) {
unsigned long r = ERR_get_error();
while (r) {
sc_error(ctx, ERR_error_string(r, NULL));
}
}
int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card,
const __u8 *in, __u8 **out, size_t *outlen)
{
__u8 pin_id;
size_t length_chat, length_pin, length_cert_desc, length_ef_cardaccess;
const __u8 *chat, *pin, *certificate_description;
__u8 *ef_cardaccess;
PACEInfo *info = NULL;
PACEDomainParameterInfo *static_dp = NULL, *eph_dp = NULL;
BUF_MEM *enc_nonce, *nonce = NULL, *mdata = NULL, *mdata_opp = NULL,
*k_enc = NULL, *k_mac = NULL, *token_opp = NULL,
*token = NULL, *pub = NULL, *pub_opp = NULL, *key = NULL;
PACE_SEC *sec = NULL;
PACE_CTX *pctx = NULL;
int r;
if (!in || !out || !outlen)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
pin_id = *in;
in++;
length_chat = *in;
in++;
chat = in;
in += length_chat;
length_pin = *in;
in++;
pin = in;
in += length_pin;
length_cert_desc = (__le16_to_cpu((__le16) *in));
in += sizeof (__le16);
certificate_description = in;
enc_nonce = BUF_MEM_new();
if (!enc_nonce) {
r = SC_ERROR_INTERNAL;
debug_ossl(ctx);
goto err;
}
r = get_ef_card_access(ctx, card, &ef_cardaccess, &length_ef_cardaccess);
if (r < 0) {
goto err;
}
if (!parse_ef_card_access(ef_cardaccess, length_ef_cardaccess,
&info, &static_dp)) {
r = SC_ERROR_INTERNAL;
debug_ossl(ctx);
goto err;
}
r = pace_mse_set_at(ctx, card, info->protocol, pin_id, 1);
if (r < 0) {
goto err;
}
r = pace_gen_auth(ctx, card, 1, NULL, 0, (u8 **) &enc_nonce->data,
&enc_nonce->length);
if (r < 0) {
goto err;
}
enc_nonce->max = enc_nonce->length;
sec = get_psec(card, (char *) pin, length_pin, pin_id);
if (!sec) {
r = SC_ERROR_INTERNAL;
debug_ossl(ctx);
goto err;
}
pctx = PACE_CTX_new();
if (!pctx || !PACE_CTX_init(pctx, info)) {
r = SC_ERROR_INTERNAL;
debug_ossl(ctx);
goto err;
}
nonce = PACE_STEP2_dec_nonce(sec, enc_nonce, pctx);
mdata_opp = BUF_MEM_new();
mdata = PACE_STEP3A_map_generate_key(static_dp, pctx);
if (!nonce || !mdata || !mdata_opp) {
r = SC_ERROR_INTERNAL;
debug_ossl(ctx);
goto err;
}
r = pace_gen_auth(ctx, card, 2, (u8 *) mdata->data, mdata->length,
(u8 **) &mdata_opp->data, &mdata_opp->length);
if (r < 0) {
goto err;
}
mdata_opp->max = mdata_opp->length;
eph_dp = PACE_STEP3A_map_compute_key(static_dp, pctx, nonce, mdata_opp);
pub = PACE_STEP3B_dh_generate_key(eph_dp, pctx);
pub_opp = BUF_MEM_new();
if (!eph_dp || !pub || !pub_opp) {
r = SC_ERROR_INTERNAL;
debug_ossl(ctx);
goto err;
}
r = pace_gen_auth(ctx, card, 3, (u8 *) pub->data, pub->length,
(u8 **) &pub_opp->data, &pub_opp->length);
if (r < 0) {
goto err;
}
pub_opp->max = pub_opp->length;
key = PACE_STEP3B_dh_compute_key(eph_dp, pctx, pub_opp);
if (!key ||
!PACE_STEP3C_derive_keys(key, pctx, &k_mac, &k_enc)) {
r = SC_ERROR_INTERNAL;
debug_ossl(ctx);
goto err;
}
token = PACE_STEP3D_compute_authentication_token(pctx,
eph_dp, info, pub_opp, k_mac, ssc);
token_opp = BUF_MEM_new();
if (!token || !token_opp) {
r = SC_ERROR_INTERNAL;
debug_ossl(ctx);
goto err;
}
r = pace_gen_auth(ctx, card, 4, (u8 *) token->data, token->length,
(u8 **) &token_opp->data, &token_opp->length);
if (r < 0) {
goto err;
}
token_opp->max = token_opp->length;
if (!PACE_STEP3D_verify_authentication_token(pctx,
eph_dp, info, pub_opp, k_mac, token_opp, ssc)) {
r = SC_ERROR_INTERNAL;
debug_ossl(ctx);
goto err;
}
/* XXX parse CHAT to check role of terminal */
err:
if (info)
PACEInfo_free(info);
if (static_dp)
PACEDomainParameterInfo_clear_free(static_dp);
if (eph_dp)
PACEDomainParameterInfo_clear_free(eph_dp);
if (enc_nonce)
BUF_MEM_free(enc_nonce);
if (nonce) {
OPENSSL_cleanse(nonce->data, nonce->length);
BUF_MEM_free(nonce);
}
if (mdata)
BUF_MEM_free(mdata);
if (mdata_opp)
BUF_MEM_free(mdata_opp);
if (k_enc) {
OPENSSL_cleanse(k_enc->data, k_enc->length);
BUF_MEM_free(k_enc);
}
if (k_mac) {
OPENSSL_cleanse(k_mac->data, k_mac->length);
BUF_MEM_free(k_mac);
}
if (token_opp)
BUF_MEM_free(token_opp);
if (token)
BUF_MEM_free(token);
if (pub)
BUF_MEM_free(pub);
if (pub_opp)
BUF_MEM_free(pub_opp);
if (key) {
OPENSSL_cleanse(key->data, key->length);
BUF_MEM_free(key);
}
if (sec)
PACE_SEC_clean_free(sec);
if (pctx)
PACE_CTX_clear_free(pctx);
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, r);
}
#endif

152
ccid/pace.h Normal file
View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2010 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _PACE_H
#define _PACE_H
#include <linux/usb/ch9.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PACE_BITMAP_PACE 0x40
#define PACE_BITMAP_EID 0x20
#define PACE_BITMAP_ESIGN 0x10
#define PACE_MRZ 0x01
#define PACE_CAN 0x02
#define PACE_PIN 0x03
#define PACE_PUK 0x04
#define FID_EF_CARDACCESS 0x011C
#define ASN1_APP_EXP_OPT(stname, field, type, tag) ASN1_EX_TYPE(ASN1_TFLG_EXPTAG|ASN1_TFLG_APPLICATION|ASN1_TFLG_OPTIONAL, tag, stname, field, type)
/*
* MSE:Set AT
*/
typedef struct pace_mse_set_at_cd_st {
ASN1_OBJECT *cryptographic_mechanism_reference;
ASN1_INTEGER *key_reference1;
ASN1_INTEGER *key_reference2;
ASN1_INTEGER *auxiliary_data;
ASN1_INTEGER *eph_pub_key;
ASN1_INTEGER *cha_template;
} PACE_MSE_SET_AT_C;
ASN1_SEQUENCE(PACE_MSE_SET_AT_C) = {
/* 0x80
* Cryptographic mechanism reference */
ASN1_IMP_OPT(PACE_MSE_SET_AT_C, cryptographic_mechanism_reference, ASN1_OBJECT, 0),
/* 0x83
* Reference of a public key / secret key */
ASN1_IMP_OPT(PACE_MSE_SET_AT_C, key_reference1, ASN1_INTEGER, 3),
/* 0x84
* Reference of a private key / Reference for computing a session key */
ASN1_IMP_OPT(PACE_MSE_SET_AT_C, key_reference2, ASN1_INTEGER, 4),
/* 0x67
* Auxiliary authenticated data */
ASN1_APP_EXP_OPT(PACE_MSE_SET_AT_C, auxiliary_data, ASN1_INTEGER, 7),
/* 0x91
* Ephemeral Public Key */
ASN1_IMP_OPT(PACE_MSE_SET_AT_C, eph_pub_key, ASN1_INTEGER, 0x11),
/* 0x7F4C
* Certificate Holder Authorization Template */
ASN1_APP_EXP_OPT(PACE_MSE_SET_AT_C, cha_template, ASN1_INTEGER, 0x4c),
} ASN1_SEQUENCE_END(PACE_MSE_SET_AT_C)
IMPLEMENT_ASN1_FUNCTIONS(PACE_MSE_SET_AT_C)
/*
* General Authenticate
*/
/* Protocol Command Data */
typedef struct pace_gen_auth_cd_st {
ASN1_OCTET_STRING *mapping_data;
ASN1_OCTET_STRING *eph_pub_key;
ASN1_OCTET_STRING *auth_token;
} PACE_GEN_AUTH_C;
ASN1_SEQUENCE(PACE_GEN_AUTH_C) = {
/* 0x81
* Mapping Data */
ASN1_IMP_OPT(PACE_GEN_AUTH_C, mapping_data, ASN1_INTEGER, 1),
/* 0x83
* Ephemeral Public Key */
ASN1_IMP_OPT(PACE_GEN_AUTH_C, eph_pub_key, ASN1_INTEGER, 3),
/* 0x85
* Authentication Token */
ASN1_IMP_OPT(PACE_GEN_AUTH_C, auth_token, ASN1_INTEGER, 5),
} ASN1_SEQUENCE_END(PACE_GEN_AUTH_C)
IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_C)
/* Protocol Response Data */
typedef struct pace_gen_auth_rapdu_body_st {
ASN1_INTEGER *enc_nonce;
ASN1_INTEGER *mapping_data;
ASN1_INTEGER *eph_pub_key;
ASN1_INTEGER *auth_token;
ASN1_INTEGER *cert_auth1;
ASN1_INTEGER *cert_auth2;
} PACE_GEN_AUTH_R_BODY;
ASN1_SEQUENCE(PACE_GEN_AUTH_R_BODY) = {
/* 0x80
* Encrypted Nonce */
ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, enc_nonce, ASN1_INTEGER, 0),
/* 0x82
* Mapping Data */
ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, mapping_data, ASN1_INTEGER, 2),
/* 0x84
* Ephemeral Public Key */
ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, eph_pub_key, ASN1_INTEGER, 4),
/* 0x86
* Authentication Token */
ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, auth_token, ASN1_INTEGER, 6),
/* 0x87
* Certification Authority Reference */
ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, cert_auth1, ASN1_INTEGER, 7),
/* 0x88
* Certification Authority Reference */
ASN1_IMP_OPT(PACE_GEN_AUTH_R_BODY, cert_auth2, ASN1_INTEGER, 8),
} ASN1_SEQUENCE_END(PACE_GEN_AUTH_R_BODY)
IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_R_BODY)
typedef PACE_GEN_AUTH_R_BODY PACE_GEN_AUTH_R;
/* 0x7C
* Dynamic Authentication Data */
ASN1_ITEM_TEMPLATE(PACE_GEN_AUTH_R) =
ASN1_EX_TEMPLATE_TYPE(
ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION,
0x1c, PACE_GEN_AUTH_R, PACE_GEN_AUTH_R_BODY)
ASN1_ITEM_TEMPLATE_END(PACE_GEN_AUTH_R)
IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_R)
int GetReadersPACECapabilities(sc_context_t *ctx, sc_card_t *card, const __u8
*in, __u8 **out, size_t *outlen);
int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card, const __u8 *in,
__u8 **out, size_t *outlen);
#ifdef __cplusplus
}
#endif
#endif