diff --git a/ccid/ccid.c b/ccid/ccid.c
index 949a8b7..85232aa 100644
--- a/ccid/ccid.c
+++ b/ccid/ccid.c
@@ -1289,7 +1289,7 @@ int ccid_testpace()
}
if (sc_card_valid(card_in_slot[i])) {
- return pace_test(ctx, card_in_slot[i]);
+ return pace_test(card_in_slot[i]);
}
}
diff --git a/ccid/pace.c b/ccid/pace.c
index 156d89a..eef2c91 100644
--- a/ccid/pace.c
+++ b/ccid/pace.c
@@ -17,6 +17,7 @@
* ccid. If not, see .
*/
#include "pace.h"
+#include "sm.h"
#include
#include
#include
@@ -135,16 +136,16 @@ IMPLEMENT_ASN1_FUNCTIONS(PACE_GEN_AUTH_R)
#ifdef NO_PACE
-inline int GetReadersPACECapabilities(sc_context_t *ctx, sc_card_t *card,
+inline int GetReadersPACECapabilities(sc_card_t *card,
const __u8 *in, __u8 **out, size_t *outlen) {
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_NOT_SUPPORTED);
+ SC_FUNC_RETURN(card->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);
+inline int EstablishPACEChannel(sc_card_t *card, const __u8 *in,
+ __u8 **out, size_t *outlen, struct sm_ctx *sm_ctx) {
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_NOT_SUPPORTED);
}
-int pace_test(sc_context_t *ctx, sc_card_t *card) {
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_NOT_SUPPORTED);
+int pace_test(sc_card_t *card) {
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_NOT_SUPPORTED);
}
#else
@@ -173,14 +174,14 @@ void bin_log(sc_context_t *ctx, const char *label, const u8 *data, size_t len)
label, len, buf);
}
-int GetReadersPACECapabilities(sc_context_t *ctx, sc_card_t *card,
+int GetReadersPACECapabilities(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);
+ SC_FUNC_RETURN(card->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);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
*out = result;
*outlen = 2;
@@ -190,11 +191,11 @@ int GetReadersPACECapabilities(sc_context_t *ctx, sc_card_t *card,
/* BitMap */
*result = PACE_BITMAP_PACE|PACE_BITMAP_EID;
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
+ SC_FUNC_RETURN(card->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,
+int get_ef_card_access(sc_card_t *card,
__u8 **ef_cardaccess, size_t *length_ef_cardaccess)
{
int r;
@@ -203,13 +204,13 @@ int get_ef_card_access(sc_context_t *ctx, sc_card_t *card,
__u8 *p;
memset(&path, 0, sizeof path);
- SC_TEST_RET(ctx, sc_append_file_id(&path, FID_EF_CARDACCESS),
+ SC_TEST_RET(card->ctx, sc_append_file_id(&path, FID_EF_CARDACCESS),
"Could not create path object.");
- SC_TEST_RET(ctx, sc_concatenate_path(&path, sc_get_mf_path(), &path),
+ SC_TEST_RET(card->ctx, sc_concatenate_path(&path, sc_get_mf_path(), &path),
"Could not create path object.");
memset(&file, 0, sizeof file);
- SC_TEST_RET(ctx, sc_select_file(card, &path, &file),
+ SC_TEST_RET(card->ctx, sc_select_file(card, &path, &file),
"Could not select EF.CardAccess.");
ssc++;
*length_ef_cardaccess = 0;
@@ -217,7 +218,7 @@ int get_ef_card_access(sc_context_t *ctx, sc_card_t *card,
while(1) {
p = realloc(*ef_cardaccess, *length_ef_cardaccess + maxresp);
if (!p)
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_OUT_OF_MEMORY);
*ef_cardaccess = p;
r = sc_read_binary(card, *length_ef_cardaccess,
@@ -229,7 +230,7 @@ int get_ef_card_access(sc_context_t *ctx, sc_card_t *card,
break;
}
- SC_TEST_RET(ctx, r, "Could not read EF.CardAccess.");
+ SC_TEST_RET(card->ctx, r, "Could not read EF.CardAccess.");
*length_ef_cardaccess += r;
}
@@ -237,12 +238,12 @@ int get_ef_card_access(sc_context_t *ctx, sc_card_t *card,
/* test cards only return an empty FCI template,
* so we can't determine any file proberties */
if (*length_ef_cardaccess < file->size)
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_FILE_TOO_SMALL);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_FILE_TOO_SMALL);
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_SUCCESS);
}
-int pace_mse_set_at(sc_context_t *ctx, sc_card_t *card,
+int pace_mse_set_at(sc_card_t *card,
int protocol, int secret_key, int reference)
{
sc_apdu_t apdu;
@@ -286,10 +287,10 @@ int pace_mse_set_at(sc_context_t *ctx, sc_card_t *card,
/* The tag/length for the sequence (0x30) is omitted in the command apdu. */
/* FIXME is there a OpenSSL way to get the value only or even a define for
* the tag? */
- apdu.data = sc_asn1_find_tag(ctx, d, r, 0x30, &apdu.datalen);
+ apdu.data = sc_asn1_find_tag(card->ctx, d, r, 0x30, &apdu.datalen);
apdu.lc = apdu.datalen;
- bin_log(ctx, "MSE:Set AT command data", apdu.data, apdu.datalen);
+ bin_log(card->ctx, "MSE:Set AT command data", apdu.data, apdu.datalen);
r = sc_transmit_apdu(card, &apdu);
ssc++;
@@ -297,7 +298,7 @@ int pace_mse_set_at(sc_context_t *ctx, sc_card_t *card,
goto err;
if (apdu.resplen) {
- sc_error(ctx, "MSE:Set AT response data should be empty");
+ sc_error(card->ctx, "MSE:Set AT response data should be empty");
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err;
}
@@ -340,10 +341,10 @@ err:
if (apdu.resplen)
free(apdu.resp);
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, r);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
}
-int pace_gen_auth(sc_context_t *ctx, sc_card_t *card,
+int pace_gen_auth(sc_card_t *card,
int step, const u8 *in, size_t in_len, u8 **out, size_t *out_len)
{
sc_apdu_t apdu;
@@ -409,7 +410,7 @@ int pace_gen_auth(sc_context_t *ctx, sc_card_t *card,
apdu.datalen = r;
apdu.lc = r;
- bin_log(ctx, "General authenticate command data", apdu.data, apdu.datalen);
+ bin_log(card->ctx, "General authenticate command data", apdu.data, apdu.datalen);
/* sanity checks in sc_transmit_apdu forbid case 4 apdus with le == 0 */
apdu.resplen = maxresp;
@@ -423,11 +424,11 @@ int pace_gen_auth(sc_context_t *ctx, sc_card_t *card,
if (r < 0)
goto err;
- bin_log(ctx, "General authenticate response data", apdu.resp, apdu.resplen);
+ bin_log(card->ctx, "General authenticate response data", apdu.resp, apdu.resplen);
if (!d2i_PACE_GEN_AUTH_R(&r_data,
(const unsigned char **) &apdu.resp, apdu.resplen)) {
- sc_error(ctx, "Could not parse general authenticate response data.");
+ sc_error(card->ctx, "Could not parse general authenticate response data.");
r = SC_ERROR_INTERNAL;
goto err;
}
@@ -438,7 +439,7 @@ int pace_gen_auth(sc_context_t *ctx, sc_card_t *card,
|| r_data->mapping_data
|| r_data->eph_pub_key
|| r_data->auth_token) {
- sc_error(ctx, "Response data of general authenticate for "
+ sc_error(card->ctx, "Response data of general authenticate for "
"step %d should (only) contain the "
"encrypted nonce.", step);
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
@@ -452,7 +453,7 @@ int pace_gen_auth(sc_context_t *ctx, sc_card_t *card,
|| !r_data->mapping_data
|| r_data->eph_pub_key
|| r_data->auth_token) {
- sc_error(ctx, "Response data of general authenticate for "
+ sc_error(card->ctx, "Response data of general authenticate for "
"step %d should (only) contain the "
"mapping data.", step);
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
@@ -466,7 +467,7 @@ int pace_gen_auth(sc_context_t *ctx, sc_card_t *card,
|| r_data->mapping_data
|| !r_data->eph_pub_key
|| r_data->auth_token) {
- sc_error(ctx, "Response data of general authenticate for "
+ sc_error(card->ctx, "Response data of general authenticate for "
"step %d should (only) contain the "
"ephemeral public key.", step);
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
@@ -480,7 +481,7 @@ int pace_gen_auth(sc_context_t *ctx, sc_card_t *card,
|| r_data->mapping_data
|| r_data->eph_pub_key
|| !r_data->auth_token) {
- sc_error(ctx, "Response data of general authenticate for "
+ sc_error(card->ctx, "Response data of general authenticate for "
"step %d should (only) contain the "
"authentication token.", step);
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
@@ -529,7 +530,7 @@ err:
//if (apdu.resplen)
//free(apdu.resp);
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, r);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
}
PACE_SEC *
@@ -585,12 +586,13 @@ void debug_ossl(sc_context_t *ctx) {
}
}
-int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card,
- const __u8 *in, __u8 **out, size_t *outlen)
+int EstablishPACEChannel(sc_card_t *card, const __u8 *in,
+ __u8 **out, size_t *outlen, struct sm_ctx *sm_ctx)
{
__u8 pin_id;
size_t length_chat, length_pin, length_cert_desc, length_ef_cardaccess;
const __u8 *chat, *pin, *certificate_description;
+ u8 *buf;
__u8 *ef_cardaccess = NULL;
PACEInfo *info = NULL;
PACEDomainParameterInfo *static_dp = NULL, *eph_dp = NULL;
@@ -602,7 +604,7 @@ int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card,
int r;
if (!in || !out || !outlen)
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
pin_id = *in;
in++;
@@ -624,42 +626,42 @@ int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card,
enc_nonce = BUF_MEM_new();
if (!enc_nonce) {
r = SC_ERROR_INTERNAL;
- debug_ossl(ctx);
+ debug_ossl(card->ctx);
goto err;
}
- r = get_ef_card_access(ctx, card, &ef_cardaccess, &length_ef_cardaccess);
+ r = get_ef_card_access(card, &ef_cardaccess, &length_ef_cardaccess);
if (r < 0) {
goto err;
}
- bin_log(ctx, "EF.CardAccess", ef_cardaccess, length_ef_cardaccess);
+ bin_log(card->ctx, "EF.CardAccess", ef_cardaccess, length_ef_cardaccess);
if (!parse_ef_card_access(ef_cardaccess, length_ef_cardaccess,
&info, &static_dp)) {
r = SC_ERROR_INTERNAL;
- debug_ossl(ctx);
+ debug_ossl(card->ctx);
goto err;
}
- r = pace_mse_set_at(ctx, card, info->protocol, pin_id, 1);
+ r = pace_mse_set_at(card, info->protocol, pin_id, 1);
if (r < 0) {
goto err;
}
- r = pace_gen_auth(ctx, card, 1, NULL, 0, (u8 **) &enc_nonce->data,
+ r = pace_gen_auth(card, 1, NULL, 0, (u8 **) &enc_nonce->data,
&enc_nonce->length);
if (r < 0) {
goto err;
}
- bin_log(ctx, "Encrypted nonce from MRTD", (u8 *)enc_nonce->data, enc_nonce->length);
+ bin_log(card->ctx, "Encrypted nonce from MRTD", (u8 *)enc_nonce->data, enc_nonce->length);
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);
+ debug_ossl(card->ctx);
goto err;
}
pctx = PACE_CTX_new();
if (!pctx || !PACE_CTX_init(pctx, info)) {
r = SC_ERROR_INTERNAL;
- debug_ossl(ctx);
+ debug_ossl(card->ctx);
goto err;
}
pctx->tr_version = PACE_TR_VERSION_2_01;
@@ -670,38 +672,38 @@ int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card,
mdata = PACE_STEP3A_generate_mapping_data(static_dp, pctx);
if (!nonce || !mdata || !mdata_opp) {
r = SC_ERROR_INTERNAL;
- debug_ossl(ctx);
+ debug_ossl(card->ctx);
goto err;
}
- r = pace_gen_auth(ctx, card, 2, (u8 *) mdata->data, mdata->length,
+ r = pace_gen_auth(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;
- bin_log(ctx, "Mapping data from MRTD", (u8 *) mdata_opp->data, mdata_opp->length);
+ bin_log(card->ctx, "Mapping data from MRTD", (u8 *) mdata_opp->data, mdata_opp->length);
eph_dp = PACE_STEP3A_map_dp(static_dp, pctx, nonce, mdata_opp);
pub = PACE_STEP3B_generate_ephemeral_key(eph_dp, pctx);
pub_opp = BUF_MEM_new();
if (!eph_dp || !pub || !pub_opp) {
r = SC_ERROR_INTERNAL;
- debug_ossl(ctx);
+ debug_ossl(card->ctx);
goto err;
}
- r = pace_gen_auth(ctx, card, 3, (u8 *) pub->data, pub->length,
+ r = pace_gen_auth(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;
- bin_log(ctx, "Public key from MRTD", (u8 *) pub_opp->data, pub_opp->length);
+ bin_log(card->ctx, "Public key from MRTD", (u8 *) pub_opp->data, pub_opp->length);
key = PACE_STEP3B_compute_ephemeral_key(eph_dp, pctx, pub_opp);
if (!key ||
!PACE_STEP3C_derive_keys(key, pctx, info, &k_mac, &k_enc)) {
r = SC_ERROR_INTERNAL;
- debug_ossl(ctx);
+ debug_ossl(card->ctx);
goto err;
}
token = PACE_STEP3D_compute_authentication_token(pctx,
@@ -709,25 +711,49 @@ int EstablishPACEChannel(sc_context_t *ctx, sc_card_t *card,
token_opp = BUF_MEM_new();
if (!token || !token_opp) {
r = SC_ERROR_INTERNAL;
- debug_ossl(ctx);
+ debug_ossl(card->ctx);
goto err;
}
- r = pace_gen_auth(ctx, card, 4, (u8 *) token->data, token->length,
+ r = pace_gen_auth(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;
- bin_log(ctx, "Authentication token from MRTD", (u8 *) token_opp->data, token_opp->length);
+ bin_log(card->ctx, "Authentication token from MRTD", (u8 *) token_opp->data, token_opp->length);
if (!PACE_STEP3D_verify_authentication_token(pctx,
eph_dp, info, k_mac, token_opp)) {
r = SC_ERROR_INTERNAL;
- debug_ossl(ctx);
+ debug_ossl(card->ctx);
goto err;
}
/* XXX parse CHAT to check role of terminal */
+ buf = realloc(sm_ctx->key_mac, k_mac->length);
+ if (!buf) {
+ r = SC_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ sm_ctx->key_mac = buf;
+ memcpy(sm_ctx->key_mac, k_mac->data, k_mac->length);
+ sm_ctx->key_mac_len = k_mac->length;
+
+ buf = realloc(sm_ctx->key_enc, k_enc->length);
+ if (!buf) {
+ r = SC_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ sm_ctx->key_enc = buf;
+ memcpy(sm_ctx->key_enc, k_enc->data, k_enc->length);
+ sm_ctx->key_enc_len = k_enc->length;
+
+ sm_ctx->cipher = pctx->cipher;
+ sm_ctx->cipher_ctx = pctx->cipher_ctx;
+ sm_ctx->cipher_engine = pctx->cipher_engine;
+ sm_ctx->md = pctx->md;
+ sm_ctx->md_ctx = pctx->md_ctx;
+ sm_ctx->md_engine = pctx->md_engine;
err:
if (info)
@@ -771,14 +797,16 @@ err:
if (pctx)
PACE_CTX_clear_free(pctx);
- SC_FUNC_RETURN(ctx, SC_LOG_TYPE_DEBUG, r);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
}
-int pace_test(sc_context_t *ctx, sc_card_t *card)
+int pace_test(sc_card_t *card)
{
__u8 in[16];
__u8 *out = NULL;
size_t outlen;
+ struct sm_ctx sm;
+ memset(&sm, 0, sizeof(sm));
in[0] = PACE_CAN; // pin_id
in[1] = 0; // length_chat
@@ -792,7 +820,8 @@ int pace_test(sc_context_t *ctx, sc_card_t *card)
in[9] = 0; // length_cert_desc
in[10]= 0; // length_cert_desc
- return EstablishPACEChannel(ctx, card, in, &out, &outlen);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR,
+ EstablishPACEChannel(card, in, &out, &outlen, &sm));
}
#endif
diff --git a/ccid/pace.h b/ccid/pace.h
index ba60f5e..51b4d61 100644
--- a/ccid/pace.h
+++ b/ccid/pace.h
@@ -19,6 +19,7 @@
#ifndef _PACE_H
#define _PACE_H
+#include "sm.h"
#include
#include
@@ -39,11 +40,11 @@ extern "C" {
#define MAX_EF_CARDACCESS 2048
-int GetReadersPACECapabilities(sc_context_t *ctx, sc_card_t *card, const __u8
+int GetReadersPACECapabilities(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);
-int pace_test(sc_context_t *ctx, sc_card_t *card);
+int EstablishPACEChannel(sc_card_t *card, const __u8 *in,
+ __u8 **out, size_t *outlen, struct sm_ctx *sm_ctx);
+int pace_test(sc_card_t *card);
#ifdef __cplusplus
}
diff --git a/ccid/sm.h b/ccid/sm.h
index 2a3da90..4c09857 100644
--- a/ccid/sm.h
+++ b/ccid/sm.h
@@ -1,6 +1,31 @@
+/*
+ * 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 .
+ */
+#ifndef _SM_H
+#define _SM_H
+
#include
#include
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define SM_ISO_PADDING 0x01
#define SM_NO_PADDING 0x02
@@ -20,3 +45,13 @@ struct sm_ctx {
EVP_MD_CTX * md_ctx;
ENGINE *md_engine;
};
+
+int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
+ const sc_apdu_t *apdu, sc_apdu_t *sm_apdu);
+int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
+ const sc_apdu_t *sm_apdu, sc_apdu_t *apdu);
+
+#ifdef __cplusplus
+}
+#endif
+#endif