- added support for verifying terminal's signature including auxiliary data (experimental, currently disabled)
- debugging openssl where possible/needed - using openssl instead of opensc for asn1 git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@556 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -539,7 +539,7 @@ main (int argc, char **argv)
|
|||||||
if (i < 0)
|
if (i < 0)
|
||||||
goto err;
|
goto err;
|
||||||
printf("Established PACE channel with %s.\n",
|
printf("Established PACE channel with %s.\n",
|
||||||
npa_secret_name(pace_input.pin_id));
|
npa_secret_name(pace_input.pin_id), file);
|
||||||
|
|
||||||
if (dotranslate) {
|
if (dotranslate) {
|
||||||
FILE *input;
|
FILE *input;
|
||||||
@@ -547,8 +547,10 @@ main (int argc, char **argv)
|
|||||||
input = stdin;
|
input = stdin;
|
||||||
else {
|
else {
|
||||||
input = fopen(file, "r");
|
input = fopen(file, "r");
|
||||||
if (!input)
|
if (!input) {
|
||||||
perror("Opening file with APDUs");
|
perror("Opening file with APDUs");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i = npa_translate_apdus(&sctx, card, input);
|
i = npa_translate_apdus(&sctx, card, input);
|
||||||
|
|||||||
248
npa/src/npa.c
248
npa/src/npa.c
@@ -28,6 +28,7 @@
|
|||||||
#include <openssl/buffer.h>
|
#include <openssl/buffer.h>
|
||||||
#include <openssl/cv_cert.h>
|
#include <openssl/cv_cert.h>
|
||||||
#include <openssl/eac.h>
|
#include <openssl/eac.h>
|
||||||
|
#include <openssl/ta.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/objects.h>
|
#include <openssl/objects.h>
|
||||||
@@ -38,16 +39,25 @@
|
|||||||
#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_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)
|
#define ASN1_APP_IMP(stname, field, type, tag) ASN1_EX_TYPE(ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION, tag, stname, field, type)
|
||||||
|
|
||||||
|
typedef CVC_DISCRETIONARY_DATA_TEMPLATES APDU_DISCRETIONARY_DATA_TEMPLATES;
|
||||||
|
DECLARE_ASN1_FUNCTIONS(APDU_DISCRETIONARY_DATA_TEMPLATES)
|
||||||
|
ASN1_ITEM_TEMPLATE(APDU_DISCRETIONARY_DATA_TEMPLATES) =
|
||||||
|
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION, 0x7,
|
||||||
|
APDU_DISCRETIONARY_DATA_TEMPLATES,
|
||||||
|
CVC_DISCRETIONARY_DATA_TEMPLATES)
|
||||||
|
ASN1_ITEM_TEMPLATE_END(APDU_DISCRETIONARY_DATA_TEMPLATES)
|
||||||
|
IMPLEMENT_ASN1_FUNCTIONS(APDU_DISCRETIONARY_DATA_TEMPLATES)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MSE:Set AT
|
* MSE:Set AT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct npa_mse_set_at_cd_st {
|
typedef struct npa_mse_set_at_cd_st {
|
||||||
ASN1_OBJECT *cryptographic_mechanism_reference;
|
ASN1_OBJECT *cryptographic_mechanism_reference;
|
||||||
ASN1_INTEGER *key_reference1;
|
ASN1_OCTET_STRING *key_reference1;
|
||||||
ASN1_INTEGER *key_reference2;
|
ASN1_OCTET_STRING *key_reference2;
|
||||||
CVC_DISCRETIONARY_DATA_TEMPLATE *auxiliary_data;
|
|
||||||
ASN1_OCTET_STRING *eph_pub_key;
|
ASN1_OCTET_STRING *eph_pub_key;
|
||||||
|
APDU_DISCRETIONARY_DATA_TEMPLATES *auxiliary_data;
|
||||||
CVC_CHAT *chat;
|
CVC_CHAT *chat;
|
||||||
} NPA_MSE_SET_AT_C;
|
} NPA_MSE_SET_AT_C;
|
||||||
ASN1_SEQUENCE(NPA_MSE_SET_AT_C) = {
|
ASN1_SEQUENCE(NPA_MSE_SET_AT_C) = {
|
||||||
@@ -56,19 +66,21 @@ ASN1_SEQUENCE(NPA_MSE_SET_AT_C) = {
|
|||||||
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, cryptographic_mechanism_reference, ASN1_OBJECT, 0),
|
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, cryptographic_mechanism_reference, ASN1_OBJECT, 0),
|
||||||
/* 0x83
|
/* 0x83
|
||||||
* Reference of a public key / secret key */
|
* Reference of a public key / secret key */
|
||||||
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, key_reference1, ASN1_INTEGER, 3),
|
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, key_reference1, ASN1_OCTET_STRING, 3),
|
||||||
/* 0x84
|
/* 0x84
|
||||||
* Reference of a private key / Reference for computing a session key */
|
* Reference of a private key / Reference for computing a session key */
|
||||||
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, key_reference2, ASN1_INTEGER, 4),
|
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, key_reference2, ASN1_OCTET_STRING, 4),
|
||||||
/* 0x67
|
|
||||||
* Auxiliary authenticated data */
|
|
||||||
ASN1_APP_IMP_OPT(NPA_MSE_SET_AT_C, auxiliary_data, CVC_DISCRETIONARY_DATA_TEMPLATE, 7),
|
|
||||||
/* 0x91
|
/* 0x91
|
||||||
* Ephemeral Public Key */
|
* Ephemeral Public Key */
|
||||||
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, eph_pub_key, ASN1_OCTET_STRING, 0x11),
|
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, eph_pub_key, ASN1_OCTET_STRING, 0x11),
|
||||||
|
/* 0x67
|
||||||
|
* Auxiliary authenticated data */
|
||||||
|
ASN1_OPT(NPA_MSE_SET_AT_C, auxiliary_data, APDU_DISCRETIONARY_DATA_TEMPLATES),
|
||||||
|
/*ASN1_APP_IMP_OPT(NPA_MSE_SET_AT_C, auxiliary_data, ASN1_OCTET_STRING, 7),*/
|
||||||
/* Certificate Holder Authorization Template */
|
/* Certificate Holder Authorization Template */
|
||||||
ASN1_OPT(NPA_MSE_SET_AT_C, chat, CVC_CHAT),
|
ASN1_OPT(NPA_MSE_SET_AT_C, chat, CVC_CHAT),
|
||||||
} ASN1_SEQUENCE_END(NPA_MSE_SET_AT_C)
|
} ASN1_SEQUENCE_END(NPA_MSE_SET_AT_C)
|
||||||
|
DECLARE_ASN1_FUNCTIONS(NPA_MSE_SET_AT_C)
|
||||||
IMPLEMENT_ASN1_FUNCTIONS(NPA_MSE_SET_AT_C)
|
IMPLEMENT_ASN1_FUNCTIONS(NPA_MSE_SET_AT_C)
|
||||||
|
|
||||||
|
|
||||||
@@ -93,6 +105,7 @@ ASN1_SEQUENCE(NPA_GEN_AUTH_C_BODY) = {
|
|||||||
* Authentication Token */
|
* Authentication Token */
|
||||||
ASN1_IMP_OPT(NPA_GEN_AUTH_C_BODY, auth_token, ASN1_OCTET_STRING, 5),
|
ASN1_IMP_OPT(NPA_GEN_AUTH_C_BODY, auth_token, ASN1_OCTET_STRING, 5),
|
||||||
} ASN1_SEQUENCE_END(NPA_GEN_AUTH_C_BODY)
|
} ASN1_SEQUENCE_END(NPA_GEN_AUTH_C_BODY)
|
||||||
|
DECLARE_ASN1_FUNCTIONS(NPA_GEN_AUTH_C_BODY)
|
||||||
IMPLEMENT_ASN1_FUNCTIONS(NPA_GEN_AUTH_C_BODY)
|
IMPLEMENT_ASN1_FUNCTIONS(NPA_GEN_AUTH_C_BODY)
|
||||||
|
|
||||||
typedef NPA_GEN_AUTH_C_BODY NPA_GEN_AUTH_C;
|
typedef NPA_GEN_AUTH_C_BODY NPA_GEN_AUTH_C;
|
||||||
@@ -103,6 +116,7 @@ ASN1_ITEM_TEMPLATE(NPA_GEN_AUTH_C) =
|
|||||||
ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION,
|
ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION,
|
||||||
0x1c, NPA_GEN_AUTH_C, NPA_GEN_AUTH_C_BODY)
|
0x1c, NPA_GEN_AUTH_C, NPA_GEN_AUTH_C_BODY)
|
||||||
ASN1_ITEM_TEMPLATE_END(NPA_GEN_AUTH_C)
|
ASN1_ITEM_TEMPLATE_END(NPA_GEN_AUTH_C)
|
||||||
|
DECLARE_ASN1_FUNCTIONS(NPA_GEN_AUTH_C)
|
||||||
IMPLEMENT_ASN1_FUNCTIONS(NPA_GEN_AUTH_C)
|
IMPLEMENT_ASN1_FUNCTIONS(NPA_GEN_AUTH_C)
|
||||||
|
|
||||||
/* Protocol Response Data */
|
/* Protocol Response Data */
|
||||||
@@ -134,6 +148,7 @@ ASN1_SEQUENCE(NPA_GEN_AUTH_R_BODY) = {
|
|||||||
* Previous Certification Authority Reference */
|
* Previous Certification Authority Reference */
|
||||||
ASN1_IMP_OPT(NPA_GEN_AUTH_R_BODY, prev_car, ASN1_OCTET_STRING, 8),
|
ASN1_IMP_OPT(NPA_GEN_AUTH_R_BODY, prev_car, ASN1_OCTET_STRING, 8),
|
||||||
} ASN1_SEQUENCE_END(NPA_GEN_AUTH_R_BODY)
|
} ASN1_SEQUENCE_END(NPA_GEN_AUTH_R_BODY)
|
||||||
|
DECLARE_ASN1_FUNCTIONS(NPA_GEN_AUTH_R_BODY)
|
||||||
IMPLEMENT_ASN1_FUNCTIONS(NPA_GEN_AUTH_R_BODY)
|
IMPLEMENT_ASN1_FUNCTIONS(NPA_GEN_AUTH_R_BODY)
|
||||||
|
|
||||||
typedef NPA_GEN_AUTH_R_BODY NPA_GEN_AUTH_R;
|
typedef NPA_GEN_AUTH_R_BODY NPA_GEN_AUTH_R;
|
||||||
@@ -144,6 +159,7 @@ ASN1_ITEM_TEMPLATE(NPA_GEN_AUTH_R) =
|
|||||||
ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION,
|
ASN1_TFLG_IMPTAG|ASN1_TFLG_APPLICATION,
|
||||||
0x1c, NPA_GEN_AUTH_R, NPA_GEN_AUTH_R_BODY)
|
0x1c, NPA_GEN_AUTH_R, NPA_GEN_AUTH_R_BODY)
|
||||||
ASN1_ITEM_TEMPLATE_END(NPA_GEN_AUTH_R)
|
ASN1_ITEM_TEMPLATE_END(NPA_GEN_AUTH_R)
|
||||||
|
DECLARE_ASN1_FUNCTIONS(NPA_GEN_AUTH_R)
|
||||||
IMPLEMENT_ASN1_FUNCTIONS(NPA_GEN_AUTH_R)
|
IMPLEMENT_ASN1_FUNCTIONS(NPA_GEN_AUTH_R)
|
||||||
|
|
||||||
|
|
||||||
@@ -166,6 +182,10 @@ struct npa_sm_ctx {
|
|||||||
BUF_MEM *auxiliary_data;
|
BUF_MEM *auxiliary_data;
|
||||||
/** Nonce generated in TA */
|
/** Nonce generated in TA */
|
||||||
BUF_MEM *nonce;
|
BUF_MEM *nonce;
|
||||||
|
/** CAR of the card's most recent imported certificate */
|
||||||
|
BUF_MEM *cur_car;
|
||||||
|
/** CHR of the certificate to be imported */
|
||||||
|
BUF_MEM *next_car;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int npa_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx,
|
static int npa_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
@@ -192,8 +212,8 @@ static int reset_ssc(struct npa_sm_ctx *eacsmctx);
|
|||||||
static struct npa_sm_ctx *
|
static struct npa_sm_ctx *
|
||||||
npa_sm_ctx_create(EAC_CTX *ctx, const unsigned char *certificate_description,
|
npa_sm_ctx_create(EAC_CTX *ctx, const unsigned char *certificate_description,
|
||||||
size_t certificate_description_length,
|
size_t certificate_description_length,
|
||||||
const unsigned char *id_icc, size_t id_icc_length
|
const unsigned char *id_icc, size_t id_icc_length,
|
||||||
)
|
const unsigned char *car, size_t car_length)
|
||||||
{
|
{
|
||||||
struct npa_sm_ctx *out = malloc(sizeof *out);
|
struct npa_sm_ctx *out = malloc(sizeof *out);
|
||||||
if (!out)
|
if (!out)
|
||||||
@@ -214,7 +234,12 @@ npa_sm_ctx_create(EAC_CTX *ctx, const unsigned char *certificate_description,
|
|||||||
if (!out->id_icc)
|
if (!out->id_icc)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
out->cur_car = BUF_MEM_create_init(car, car_length);
|
||||||
|
if (!out->cur_car)
|
||||||
|
goto err;
|
||||||
|
|
||||||
out->nonce = NULL;
|
out->nonce = NULL;
|
||||||
|
out->next_car = NULL;
|
||||||
out->eph_pub_key = NULL;
|
out->eph_pub_key = NULL;
|
||||||
out->auxiliary_data = NULL;
|
out->auxiliary_data = NULL;
|
||||||
|
|
||||||
@@ -253,7 +278,7 @@ int get_ef_card_access(sc_card_t *card,
|
|||||||
sc_file_t *file = NULL;
|
sc_file_t *file = NULL;
|
||||||
u8 *p;
|
u8 *p;
|
||||||
|
|
||||||
if (!ef_cardaccess || !length_ef_cardaccess) {
|
if (!card || !ef_cardaccess || !length_ef_cardaccess) {
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -325,11 +350,13 @@ static int npa_mse_set_at(struct sm_ctx *oldnpactx, sc_card_t *card,
|
|||||||
sc_apdu_t apdu;
|
sc_apdu_t apdu;
|
||||||
unsigned char *d = NULL;
|
unsigned char *d = NULL;
|
||||||
NPA_MSE_SET_AT_C *data = NULL;
|
NPA_MSE_SET_AT_C *data = NULL;
|
||||||
int r, tries;
|
int r, tries, class, tag;
|
||||||
|
long length;
|
||||||
|
const unsigned char *p;
|
||||||
|
|
||||||
memset(&apdu, 0, sizeof apdu);
|
memset(&apdu, 0, sizeof apdu);
|
||||||
|
|
||||||
if (!sw1 || !sw2) {
|
if (!card || !sw1 || !sw2) {
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -358,6 +385,7 @@ static int npa_mse_set_at(struct sm_ctx *oldnpactx, sc_card_t *card,
|
|||||||
|
|
||||||
if (!ASN1_INTEGER_set(data->key_reference1, secret_key)) {
|
if (!ASN1_INTEGER_set(data->key_reference1, secret_key)) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Error setting key reference 1 of MSE:Set AT data");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Error setting key reference 1 of MSE:Set AT data");
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -366,16 +394,17 @@ static int npa_mse_set_at(struct sm_ctx *oldnpactx, sc_card_t *card,
|
|||||||
|
|
||||||
|
|
||||||
r = i2d_NPA_MSE_SET_AT_C(data, &d);
|
r = i2d_NPA_MSE_SET_AT_C(data, &d);
|
||||||
if (r < 0) {
|
p = d;
|
||||||
|
if (r < 0
|
||||||
|
|| (0x80 & ASN1_get_object(&p, &length, &tag, &class, r))) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Error encoding MSE:Set AT APDU data");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Error encoding MSE:Set AT APDU data");
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
/* The tag/length for the sequence (0x30) is omitted in the command apdu. */
|
apdu.data = p;
|
||||||
/* XXX is there a OpenSSL way to get the value only or even a define for
|
apdu.datalen = length;
|
||||||
* the tag? */
|
apdu.lc = length;
|
||||||
apdu.data = sc_asn1_find_tag(card->ctx, d, r, 0x30, &apdu.datalen);
|
|
||||||
apdu.lc = apdu.datalen;
|
|
||||||
|
|
||||||
bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "MSE:Set AT command data", apdu.data, apdu.datalen);
|
bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "MSE:Set AT command data", apdu.data, apdu.datalen);
|
||||||
|
|
||||||
@@ -457,6 +486,7 @@ static int npa_gen_auth_1_encrypted_nonce(struct sm_ctx *oldnpactx,
|
|||||||
}
|
}
|
||||||
r = i2d_NPA_GEN_AUTH_C(c_data, &d);
|
r = i2d_NPA_GEN_AUTH_C(c_data, &d);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -484,6 +514,7 @@ static int npa_gen_auth_1_encrypted_nonce(struct sm_ctx *oldnpactx,
|
|||||||
if (!d2i_NPA_GEN_AUTH_R(&r_data,
|
if (!d2i_NPA_GEN_AUTH_R(&r_data,
|
||||||
(const unsigned char **) &apdu.resp, apdu.resplen)) {
|
(const unsigned char **) &apdu.resp, apdu.resplen)) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -547,11 +578,13 @@ static int npa_gen_auth_2_map_nonce(struct sm_ctx *oldnpactx,
|
|||||||
if (!c_data->mapping_data
|
if (!c_data->mapping_data
|
||||||
|| !M_ASN1_OCTET_STRING_set(
|
|| !M_ASN1_OCTET_STRING_set(
|
||||||
c_data->mapping_data, in, in_len)) {
|
c_data->mapping_data, in, in_len)) {
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
r = i2d_NPA_GEN_AUTH_C(c_data, &d);
|
r = i2d_NPA_GEN_AUTH_C(c_data, &d);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -579,6 +612,7 @@ static int npa_gen_auth_2_map_nonce(struct sm_ctx *oldnpactx,
|
|||||||
if (!d2i_NPA_GEN_AUTH_R(&r_data,
|
if (!d2i_NPA_GEN_AUTH_R(&r_data,
|
||||||
(const unsigned char **) &apdu.resp, apdu.resplen)) {
|
(const unsigned char **) &apdu.resp, apdu.resplen)) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -642,11 +676,13 @@ static int npa_gen_auth_3_perform_key_agreement(
|
|||||||
if (!c_data->eph_pub_key
|
if (!c_data->eph_pub_key
|
||||||
|| !M_ASN1_OCTET_STRING_set(
|
|| !M_ASN1_OCTET_STRING_set(
|
||||||
c_data->eph_pub_key, in, in_len)) {
|
c_data->eph_pub_key, in, in_len)) {
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
r = i2d_NPA_GEN_AUTH_C(c_data, &d);
|
r = i2d_NPA_GEN_AUTH_C(c_data, &d);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -674,6 +710,7 @@ static int npa_gen_auth_3_perform_key_agreement(
|
|||||||
if (!d2i_NPA_GEN_AUTH_R(&r_data,
|
if (!d2i_NPA_GEN_AUTH_R(&r_data,
|
||||||
(const unsigned char **) &apdu.resp, apdu.resplen)) {
|
(const unsigned char **) &apdu.resp, apdu.resplen)) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -740,11 +777,13 @@ static int npa_gen_auth_4_mutual_authentication(
|
|||||||
if (!c_data->auth_token
|
if (!c_data->auth_token
|
||||||
|| !M_ASN1_OCTET_STRING_set(
|
|| !M_ASN1_OCTET_STRING_set(
|
||||||
c_data->auth_token, in, in_len)) {
|
c_data->auth_token, in, in_len)) {
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
r = i2d_NPA_GEN_AUTH_C(c_data, &d);
|
r = i2d_NPA_GEN_AUTH_C(c_data, &d);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -772,6 +811,7 @@ static int npa_gen_auth_4_mutual_authentication(
|
|||||||
if (!d2i_NPA_GEN_AUTH_R(&r_data,
|
if (!d2i_NPA_GEN_AUTH_R(&r_data,
|
||||||
(const unsigned char **) &apdu.resp, apdu.resplen)) {
|
(const unsigned char **) &apdu.resp, apdu.resplen)) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -787,7 +827,6 @@ static int npa_gen_auth_4_mutual_authentication(
|
|||||||
}
|
}
|
||||||
p = r_data->auth_token->data;
|
p = r_data->auth_token->data;
|
||||||
l = r_data->auth_token->length;
|
l = r_data->auth_token->length;
|
||||||
/* XXX CAR sould be returned as result in some way */
|
|
||||||
if (r_data->cur_car) {
|
if (r_data->cur_car) {
|
||||||
bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Most recent Certificate Authority Reference",
|
bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Most recent Certificate Authority Reference",
|
||||||
r_data->cur_car->data, r_data->cur_car->length);
|
r_data->cur_car->data, r_data->cur_car->length);
|
||||||
@@ -948,10 +987,9 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
|
|||||||
BIO *bio_stdout = NULL;
|
BIO *bio_stdout = NULL;
|
||||||
CVC_CERTIFICATE_DESCRIPTION *desc = NULL;
|
CVC_CERTIFICATE_DESCRIPTION *desc = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
const unsigned char *pp;
|
||||||
|
|
||||||
if (!card)
|
if (!card || !pace_output || !sctx)
|
||||||
return SC_ERROR_CARD_NOT_PRESENT;
|
|
||||||
if (!pace_output || !sctx)
|
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
/* show description in advance to give the user more time to read it...
|
/* show description in advance to give the user more time to read it...
|
||||||
@@ -959,10 +997,11 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
|
|||||||
if (pace_input.certificate_description_length &&
|
if (pace_input.certificate_description_length &&
|
||||||
pace_input.certificate_description) {
|
pace_input.certificate_description) {
|
||||||
|
|
||||||
const unsigned char *pp = pace_input.certificate_description;
|
pp = pace_input.certificate_description;
|
||||||
if (!d2i_CVC_CERTIFICATE_DESCRIPTION(&desc,
|
if (!d2i_CVC_CERTIFICATE_DESCRIPTION(&desc,
|
||||||
&pp, pace_input.certificate_description_length)) {
|
&pp, pace_input.certificate_description_length)) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse certificate description.");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse certificate description.");
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1021,9 +1060,10 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d2i_CVC_CHAT(&chat, (const unsigned char **) &pace_input.chat,
|
pp = pace_input.chat;
|
||||||
pace_input.chat_length)) {
|
if (!d2i_CVC_CHAT(&chat, &pp, pace_input.chat_length)) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse card holder authorization template (CHAT).");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse card holder authorization template (CHAT).");
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1069,7 +1109,8 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
|
|||||||
}
|
}
|
||||||
enc_nonce = BUF_MEM_new();
|
enc_nonce = BUF_MEM_new();
|
||||||
if (!enc_nonce) {
|
if (!enc_nonce) {
|
||||||
r = SC_ERROR_INTERNAL;
|
ssl_error(card->ctx);
|
||||||
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
r = npa_gen_auth_1_encrypted_nonce(oldnpactx, card, (u8 **) &enc_nonce->data,
|
r = npa_gen_auth_1_encrypted_nonce(oldnpactx, card, (u8 **) &enc_nonce->data,
|
||||||
@@ -1227,12 +1268,15 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
|
|||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
eac_ctx->ta_ctx->flags |= TA_FLAG_SKIP_TIMECHECK;
|
||||||
|
|
||||||
sctx->priv_data = npa_sm_ctx_create(eac_ctx,
|
sctx->priv_data = npa_sm_ctx_create(eac_ctx,
|
||||||
pace_input.certificate_description,
|
pace_input.certificate_description,
|
||||||
pace_input.certificate_description_length,
|
pace_input.certificate_description_length,
|
||||||
pace_output->id_icc,
|
pace_output->id_icc,
|
||||||
pace_output->id_icc_length);
|
pace_output->id_icc_length,
|
||||||
|
pace_output->recent_car,
|
||||||
|
pace_output->recent_car_length);
|
||||||
if (!sctx->priv_data) {
|
if (!sctx->priv_data) {
|
||||||
r = SC_ERROR_OUT_OF_MEMORY;
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1346,7 +1390,7 @@ npa_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
u8 *p = NULL;
|
u8 *p = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!ctx || !enc || !ctx->priv_data) {
|
if (!card || !ctx || !enc || !ctx->priv_data) {
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1390,7 +1434,7 @@ npa_sm_decrypt(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
u8 *p = NULL;
|
u8 *p = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!ctx || !enc || !ctx->priv_data || !data) {
|
if (!card || !ctx || !enc || !ctx->priv_data || !data) {
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1434,7 +1478,7 @@ npa_sm_authenticate(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
u8 *p = NULL, *ssc = NULL;
|
u8 *p = NULL, *ssc = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!ctx || !ctx->priv_data || !macdata) {
|
if (!card || !ctx || !ctx->priv_data || !macdata) {
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1477,7 +1521,7 @@ npa_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
char *p;
|
char *p;
|
||||||
BUF_MEM *my_mac = NULL;
|
BUF_MEM *my_mac = NULL;
|
||||||
|
|
||||||
if (!ctx || !ctx->priv_data) {
|
if (!card || !ctx || !ctx->priv_data) {
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1512,38 +1556,33 @@ err:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CVC_CERT *
|
static int
|
||||||
cert_from_apdudata(const unsigned char *data, size_t len)
|
add_tag(unsigned char **asn1new, int constructed, int tag,
|
||||||
|
int xclass, const unsigned char *data, size_t len)
|
||||||
{
|
{
|
||||||
/* there MUST be a more elegant way to do this... */
|
unsigned char *p;
|
||||||
CVC_CERT *cert = NULL;
|
int newlen;
|
||||||
long int asn1datalen = len;
|
|
||||||
int tag, xclass;
|
|
||||||
const unsigned char *p = data;
|
|
||||||
|
|
||||||
cert = CVC_CERT_new();
|
if (!asn1new || !data)
|
||||||
if (!cert)
|
return -1;
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (0x80 & ASN1_get_object(&p, &asn1datalen, &tag, &xclass, len)
|
newlen = ASN1_object_size(constructed, len, tag);
|
||||||
|| !d2i_CVC_CERT_BODY(&cert->body, &data, (p-data)+asn1datalen))
|
if (newlen < 0)
|
||||||
goto err;
|
return newlen;
|
||||||
|
|
||||||
p += asn1datalen;
|
p = OPENSSL_realloc(*asn1new, newlen);
|
||||||
if (0x80 & ASN1_get_object(&p, &asn1datalen, &tag, &xclass, len-(p-data))
|
if (!p)
|
||||||
|| tag != 0x37)
|
return -1;
|
||||||
goto err;
|
*asn1new = p;
|
||||||
cert->signature = ASN1_OCTET_STRING_new();
|
|
||||||
if (!cert->signature
|
|
||||||
|| !ASN1_OCTET_STRING_set(cert->signature, p, asn1datalen))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
return cert;
|
ASN1_put_object(&p, constructed, len, tag, xclass);
|
||||||
|
memcpy(p, data, len);
|
||||||
|
|
||||||
err:
|
return newlen;
|
||||||
if (cert)
|
|
||||||
CVC_CERT_free(cert);
|
|
||||||
}
|
}
|
||||||
|
extern int
|
||||||
|
cvc_certificate_extension_print(BIO *bio,
|
||||||
|
CVC_DISCRETIONARY_DATA_TEMPLATE *extension, int indent);
|
||||||
static int
|
static int
|
||||||
npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
sc_apdu_t *apdu)
|
sc_apdu_t *apdu)
|
||||||
@@ -1555,25 +1594,35 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
BUF_MEM *signature = NULL;
|
BUF_MEM *signature = NULL;
|
||||||
unsigned char *sequence = NULL;
|
unsigned char *sequence = NULL;
|
||||||
NPA_MSE_SET_AT_C *msesetat = NULL;
|
NPA_MSE_SET_AT_C *msesetat = NULL;
|
||||||
|
const unsigned char *p;
|
||||||
|
|
||||||
if (!ctx) {
|
if (!card || !ctx || !apdu || !ctx->priv_data) {
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct npa_sm_ctx *eacsmctx = ctx->priv_data;
|
struct npa_sm_ctx *eacsmctx = ctx->priv_data;
|
||||||
if (!ctx) {
|
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
if (apdu->ins == 0x22 && apdu->p1 == 0x81 && apdu->p2 == 0xbe) {
|
||||||
|
/* MSE:Set DST
|
||||||
|
* setup certificate verification for TA */
|
||||||
|
|
||||||
|
if (!eacsmctx->cur_car || !eacsmctx->cur_car->length != apdu->datalen
|
||||||
|
|| memcmp(eacsmctx->cur_car->data, apdu->data, apdu->datalen) != 0) {
|
||||||
|
r = SC_ERROR_INVALID_DATA;
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
||||||
|
"CAR doesn't match the most recent imported certificate");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "CAR matches the most recent imported certificate");
|
||||||
|
|
||||||
if (apdu && apdu->ins == 0x2a && apdu->p1 == 0x00 && apdu->p2 == 0xbe) {
|
} else if (apdu->ins == 0x2a && apdu->p1 == 0x00 && apdu->p2 == 0xbe) {
|
||||||
/* PSO:Verify Certificate
|
/* PSO:Verify Certificate
|
||||||
* check certificate description to match given certificate
|
* check certificate description to match given certificate */
|
||||||
* TODO take MSE:Set DST (sent before) into account */
|
|
||||||
cvc_cert = cert_from_apdudata(apdu->data, apdu->datalen);
|
|
||||||
|
|
||||||
if (!cvc_cert || !cvc_cert->body) {
|
len = add_tag(&cert, 1, 0x21, V_ASN1_APPLICATION, apdu->data, apdu->datalen);
|
||||||
|
p = cert;
|
||||||
|
if (len < 0 || !d2i_CVC_CERT(&cvc_cert, &p, len)
|
||||||
|
|| !cvc_cert || !cvc_cert->body) {
|
||||||
r = SC_ERROR_INVALID_DATA;
|
r = SC_ERROR_INVALID_DATA;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1628,9 +1677,7 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = i2d_CVC_CERT(cvc_cert, &cert);
|
if (!TA_STEP2_import_certificate(eacsmctx->ctx, cert, len)) {
|
||||||
if (len < 0
|
|
||||||
|| !TA_STEP2_import_certificate(eacsmctx->ctx, cert, len)) {
|
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
||||||
"Error importing certificate");
|
"Error importing certificate");
|
||||||
ssl_error(card->ctx);
|
ssl_error(card->ctx);
|
||||||
@@ -1638,18 +1685,32 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (apdu && apdu->ins == 0x22 && apdu->p1 == 0x81 && apdu->p2 == 0xa4) {
|
if (eacsmctx->next_car)
|
||||||
|
BUF_MEM_free(eacsmctx->next_car);
|
||||||
|
if (cvc_cert->body->certificate_holder_reference) {
|
||||||
|
eacsmctx->next_car = BUF_MEM_create_init(apdu->data, apdu->datalen);
|
||||||
|
if (!eacsmctx->next_car) {
|
||||||
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eacsmctx->next_car = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
} else if (apdu->ins == 0x22 && apdu->p1 == 0x81 && apdu->p2 == 0xa4) {
|
||||||
/* MSE:Set AT
|
/* MSE:Set AT
|
||||||
* fetch auxiliary data and terminal's compressed ephemeral public key
|
* fetch auxiliary data and terminal's compressed ephemeral public key
|
||||||
* for CA */
|
* for CA */
|
||||||
len = ASN1_object_size(1, apdu->datalen, V_ASN1_SEQUENCE);
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Parse MSE:Set AT.");
|
||||||
sequence = malloc(len);
|
|
||||||
unsigned char *p = sequence;
|
len = add_tag(&sequence, 1, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, apdu->data, apdu->datalen);
|
||||||
const unsigned char *pp = sequence;
|
p = sequence;
|
||||||
ASN1_put_object(&p, 1, apdu->datalen, V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
|
bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "sequence", sequence,
|
||||||
memcpy(p, apdu->data, apdu->datalen);
|
len);
|
||||||
if (!d2i_NPA_MSE_SET_AT_C(&msesetat, &pp, len)) {
|
if (len < 0 || !d2i_NPA_MSE_SET_AT_C(&msesetat, &p, len)) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse MSE:Set AT.");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse MSE:Set AT. %d", len);
|
||||||
|
ssl_error(card->ctx);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1663,7 +1724,7 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
eacsmctx->auxiliary_data->length =
|
eacsmctx->auxiliary_data->length =
|
||||||
i2d_CVC_DISCRETIONARY_DATA_TEMPLATE(msesetat->auxiliary_data,
|
i2d_APDU_DISCRETIONARY_DATA_TEMPLATES(msesetat->auxiliary_data,
|
||||||
(unsigned char **) &eacsmctx->auxiliary_data->data);
|
(unsigned char **) &eacsmctx->auxiliary_data->data);
|
||||||
if ((int) eacsmctx->auxiliary_data->length < 0) {
|
if ((int) eacsmctx->auxiliary_data->length < 0) {
|
||||||
r = SC_ERROR_OUT_OF_MEMORY;
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
@@ -1683,7 +1744,8 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (apdu && apdu->ins == 0x82 && apdu->p1 == 0x00 && apdu->p2 == 0x00) {
|
|
||||||
|
} else if (apdu->ins == 0x82 && apdu->p1 == 0x00 && apdu->p2 == 0x00) {
|
||||||
/* External Authenticate
|
/* External Authenticate
|
||||||
* check terminal's signature */
|
* check terminal's signature */
|
||||||
|
|
||||||
@@ -1714,6 +1776,9 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
r = increment_ssc(ctx->priv_data);
|
r = increment_ssc(ctx->priv_data);
|
||||||
|
|
||||||
@@ -1742,15 +1807,25 @@ static int
|
|||||||
npa_sm_finish(sc_card_t *card, const struct sm_ctx *ctx,
|
npa_sm_finish(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
sc_apdu_t *apdu)
|
sc_apdu_t *apdu)
|
||||||
{
|
{
|
||||||
if (!ctx || !ctx->priv_data)
|
if (!card || !ctx || !ctx->priv_data || !apdu || !card)
|
||||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
|
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||||
SC_ERROR_INVALID_ARGUMENTS);
|
SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
struct npa_sm_ctx *eacsmctx = ctx->priv_data;
|
||||||
|
|
||||||
if (apdu && apdu->ins == 0x84 && apdu->p1 == 0x00 && apdu->p2 == 0x00 && apdu->le == 8
|
if (apdu->sw1 == 0x90 && apdu->sw2 == 0x00) {
|
||||||
&& apdu->sw1 == 0x90 && apdu->sw2 == 0x00 && apdu->resplen == 8) {
|
if (apdu->ins == 0x2a && apdu->p1 == 0x00 && apdu->p2 == 0xbe) {
|
||||||
|
/* PSO:Verify Certificate
|
||||||
|
* copy the currently imported certificate's CHR to the current CAR */
|
||||||
|
|
||||||
|
if (eacsmctx->cur_car)
|
||||||
|
BUF_MEM_free(eacsmctx->cur_car);
|
||||||
|
eacsmctx->cur_car = eacsmctx->next_car;
|
||||||
|
eacsmctx->next_car = NULL;
|
||||||
|
|
||||||
|
} else if (apdu->ins == 0x84 && apdu->p1 == 0x00 && apdu->p2 == 0x00
|
||||||
|
&& apdu->le == 8 && apdu->resplen == 8) {
|
||||||
/* Get Challenge
|
/* Get Challenge
|
||||||
* copy challenge to EAC context */
|
* copy challenge to EAC context */
|
||||||
struct npa_sm_ctx *eacsmctx = ctx->priv_data;
|
|
||||||
|
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Saving MRTD's nonce to later verify Terminal's signature");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Saving MRTD's nonce to later verify Terminal's signature");
|
||||||
|
|
||||||
@@ -1762,6 +1837,7 @@ npa_sm_finish(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
|
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||||
SC_ERROR_OUT_OF_MEMORY);
|
SC_ERROR_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, 0);
|
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, 0);
|
||||||
}
|
}
|
||||||
@@ -1784,6 +1860,10 @@ npa_sm_clear_free(const struct sm_ctx *ctx)
|
|||||||
BUF_MEM_free(eacsmctx->eph_pub_key);
|
BUF_MEM_free(eacsmctx->eph_pub_key);
|
||||||
if (eacsmctx->auxiliary_data)
|
if (eacsmctx->auxiliary_data)
|
||||||
BUF_MEM_free(eacsmctx->auxiliary_data);
|
BUF_MEM_free(eacsmctx->auxiliary_data);
|
||||||
|
if (eacsmctx->cur_car)
|
||||||
|
BUF_MEM_free(eacsmctx->cur_car);
|
||||||
|
if (eacsmctx->next_car)
|
||||||
|
BUF_MEM_free(eacsmctx->next_car);
|
||||||
free(eacsmctx);
|
free(eacsmctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user