dnie: changes to include DNIe 3.0 (PIN channel)
This commit is contained in:
parent
65090e814e
commit
1d051dba6a
|
@ -59,7 +59,6 @@
|
|||
/* default titles */
|
||||
#define USER_CONSENT_TITLE "Confirm"
|
||||
|
||||
extern cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card);
|
||||
extern int dnie_read_file(
|
||||
sc_card_t * card,
|
||||
const sc_path_t * path,
|
||||
|
@ -749,10 +748,6 @@ int dnie_match_card(struct sc_card *card)
|
|||
LOG_FUNC_CALLED(card->ctx);
|
||||
matched = _sc_match_atr(card, dnie_atrs, &card->type);
|
||||
result = (matched >= 0) ? 1 : 0;
|
||||
if (result && card->atr.value[15] >= 0x04) {
|
||||
/* exclude DNIe 3.0 */
|
||||
result = 0;
|
||||
}
|
||||
LOG_FUNC_RETURN(card->ctx, result);
|
||||
}
|
||||
|
||||
|
@ -769,13 +764,15 @@ static int dnie_sm_free_wrapped_apdu(struct sc_card *card,
|
|||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
|
||||
if ((*sm_apdu) != plain) {
|
||||
if (plain) {
|
||||
plain->resp = (*sm_apdu)->resp;
|
||||
plain->resplen = (*sm_apdu)->resplen;
|
||||
plain->sw1 = (*sm_apdu)->sw1;
|
||||
plain->sw2 = (*sm_apdu)->sw2;
|
||||
|
||||
if (((*sm_apdu)->data) != plain->data)
|
||||
free((unsigned char *) (*sm_apdu)->data);
|
||||
}
|
||||
|
||||
free(*sm_apdu);
|
||||
}
|
||||
*sm_apdu = NULL;
|
||||
|
@ -2195,6 +2192,11 @@ static int dnie_pin_verify(struct sc_card *card,
|
|||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
/* ensure that secure channel is established from reset */
|
||||
if (card->atr.value[15] >= DNIE_30_VERSION) {
|
||||
/* the provider should be prepared for using PIN information */
|
||||
sc_log(card->ctx, "DNIe 3.0 detected doing PIN initialization");
|
||||
dnie_change_cwa_provider_to_pin(card);
|
||||
}
|
||||
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_COLD);
|
||||
LOG_TEST_RET(card->ctx, res, "Establish SM failed");
|
||||
|
||||
|
@ -2232,6 +2234,14 @@ static int dnie_pin_verify(struct sc_card *card,
|
|||
/* the end: a bit of Mister Proper and return */
|
||||
dnie_free_apdu_buffers(&apdu, resp, MAX_RESP_BUFFER_SIZE);
|
||||
data->apdu = NULL;
|
||||
|
||||
/* ensure that secure channel is established after a PIN channel in 3.0 */
|
||||
if (card->atr.value[15] >= DNIE_30_VERSION) {
|
||||
sc_log(card->ctx, "DNIe 3.0 detected => re-establish secure channel");
|
||||
dnie_change_cwa_provider_to_secure(card);
|
||||
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_OVER);
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, res);
|
||||
#else
|
||||
LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "built without support of SM and External Authentication");
|
||||
|
|
|
@ -90,6 +90,23 @@ static u8 ifd_modulus[] = {
|
|||
0x6a, 0xe2, 0x36, 0x59, 0x00, 0x16, 0xba, 0x69
|
||||
};
|
||||
|
||||
/**
|
||||
* Terminal (IFD) key modulus for SM channel creation for PIN channel DNIe 3.0
|
||||
*/
|
||||
static u8 ifd_pin_modulus[] = {
|
||||
0xF4, 0x27, 0x97, 0x8D, 0xA1, 0x59, 0xBA, 0x02, 0x79, 0x30, 0x8A, 0x6C,
|
||||
0x6A, 0x89, 0x50, 0x5A, 0xDA, 0x5A, 0x67, 0xC3, 0xDA, 0x26, 0x79, 0xEA,
|
||||
0xF4, 0xA1, 0xB0, 0x11, 0x9E, 0xDD, 0x4D, 0xF4, 0x6E, 0x78, 0x04, 0x24,
|
||||
0x71, 0xA9, 0xD1, 0x30, 0x1D, 0x3F, 0xB2, 0x8F, 0x38, 0xC5, 0x7D, 0x08,
|
||||
0x89, 0xF7, 0x31, 0xDB, 0x8E, 0xDD, 0xBC, 0x13, 0x67, 0xC1, 0x34, 0xE1,
|
||||
0xE9, 0x47, 0x78, 0x6B, 0x8E, 0xC8, 0xE4, 0xB9, 0xCA, 0x6A, 0xA7, 0xC2,
|
||||
0x4C, 0x86, 0x91, 0xC7, 0xBE, 0x2F, 0xD8, 0xC1, 0x23, 0x66, 0x0E, 0x98,
|
||||
0x65, 0xE1, 0x4F, 0x19, 0xDF, 0xFB, 0xB7, 0xFF, 0x38, 0x08, 0xC9, 0xF2,
|
||||
0x04, 0xE7, 0x97, 0xD0, 0x6D, 0xD8, 0x33, 0x3A, 0xC5, 0x83, 0x86, 0xEE,
|
||||
0x4E, 0xB6, 0x1E, 0x20, 0xEC, 0xA7, 0xEF, 0x38, 0xD5, 0xB0, 0x5E, 0xB1,
|
||||
0x15, 0x96, 0x6A, 0x5A, 0x89, 0xAD, 0x58, 0xA5
|
||||
};
|
||||
|
||||
/**
|
||||
* Terminal (IFD) public exponent for SM channel creation
|
||||
*/
|
||||
|
@ -97,6 +114,13 @@ static u8 ifd_public_exponent[] = {
|
|||
0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
/**
|
||||
* Terminal (IFD) public exponent for SM channel creation for PIN channel DNIe 3.0
|
||||
*/
|
||||
static u8 ifd_pin_public_exponent[] = {
|
||||
0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
/**
|
||||
* Terminal (IFD) private exponent for SM channel establishment
|
||||
*/
|
||||
|
@ -114,6 +138,23 @@ static u8 ifd_private_exponent[] = {
|
|||
0xbd, 0x9b, 0x00, 0x31, 0x3c, 0x0f, 0x46, 0xed
|
||||
};
|
||||
|
||||
/**
|
||||
* Terminal (IFD) private exponent for SM channel establishment for PIN channel DNIe 3.0
|
||||
*/
|
||||
static u8 ifd_pin_private_exponent[] = {
|
||||
0xD2, 0x7A, 0x03, 0x23, 0x7C, 0x72, 0x2E, 0x71, 0x8D, 0x69, 0xF4, 0x1A,
|
||||
0xEC, 0x68, 0xBD, 0x95, 0xE4, 0xE0, 0xC4, 0xCD, 0x49, 0x15, 0x9C, 0x4A,
|
||||
0x99, 0x63, 0x7D, 0xB6, 0x62, 0xFE, 0xA3, 0x02, 0x51, 0xED, 0x32, 0x9C,
|
||||
0xFC, 0x43, 0x89, 0xEB, 0x71, 0x7B, 0x85, 0x02, 0x04, 0xCD, 0xF3, 0x30,
|
||||
0xD6, 0x46, 0xFC, 0x7B, 0x2B, 0x19, 0x29, 0xD6, 0x8C, 0xBE, 0x39, 0x49,
|
||||
0x7B, 0x62, 0x3A, 0x82, 0xC7, 0x64, 0x1A, 0xC3, 0x48, 0x79, 0x57, 0x3D,
|
||||
0xEA, 0x0D, 0xAB, 0xC7, 0xCA, 0x30, 0x9A, 0xE4, 0xB3, 0xED, 0xDA, 0xFA,
|
||||
0xEE, 0x55, 0xD5, 0x42, 0xF7, 0x80, 0x23, 0x03, 0x51, 0xE7, 0x5E, 0x7F,
|
||||
0x32, 0xDC, 0x65, 0x2E, 0xF1, 0xED, 0x47, 0xA5, 0x1C, 0x18, 0xD9, 0xDF,
|
||||
0x9F, 0xF4, 0x8D, 0x87, 0x8D, 0xB6, 0x22, 0xEA, 0x6E, 0x93, 0x70, 0xE9,
|
||||
0xC6, 0x3B, 0x35, 0x8B, 0x7C, 0x11, 0x5A, 0xA1
|
||||
};
|
||||
|
||||
/**
|
||||
* Intermediate CA certificate in CVC format (Card verifiable certificate)
|
||||
*/
|
||||
|
@ -162,6 +203,30 @@ static u8 C_CV_IFDUser_AUT_cert[] = {
|
|||
0x44, 0x49, 0x60, 0x00, 0x06
|
||||
};
|
||||
|
||||
/**
|
||||
* Terminal (IFD) certificate in CVC format (PK.IFD.AUT) for the PIN channel in DNIe 3.0
|
||||
*/
|
||||
static u8 C_CV_IFDUser_AUT_pin_cert[] = {
|
||||
0x7f, 0x21, 0x81, 0xcd, 0x5f, 0x37, 0x81, 0x80, 0x69, 0xc4, 0xe4, 0x94,
|
||||
0xf0, 0x08, 0xe2, 0x42, 0x14, 0xb1, 0xc1, 0x31, 0xb6, 0x1f, 0xce, 0x9c,
|
||||
0x15, 0xfa, 0x3c, 0xb0, 0x61, 0xdd, 0x6f, 0x02, 0xd8, 0xa2, 0xcd, 0x30,
|
||||
0xd7, 0x2f, 0xb6, 0xdf, 0x89, 0x9a, 0xf1, 0x5b, 0x71, 0x78, 0x21, 0xbf,
|
||||
0xb1, 0xaf, 0x7d, 0x75, 0x85, 0x01, 0x6d, 0x8c, 0x36, 0xaf, 0x4a, 0xc2,
|
||||
0xa0, 0xb0, 0xc5, 0x2a, 0xd6, 0x5b, 0x69, 0x25, 0x67, 0x31, 0xc3, 0x4d,
|
||||
0x59, 0x02, 0x0e, 0x87, 0xab, 0x73, 0xa2, 0x30, 0xfa, 0x69, 0xee, 0x82,
|
||||
0xb3, 0x3a, 0x31, 0xdf, 0x04, 0x0c, 0xe9, 0x0f, 0x0a, 0xfc, 0x3a, 0x11,
|
||||
0x1d, 0x35, 0xda, 0x95, 0x66, 0xa8, 0xcd, 0xab, 0xea, 0x0e, 0x3f, 0x75,
|
||||
0x94, 0xc4, 0x40, 0xd3, 0x74, 0x50, 0x7a, 0x94, 0x35, 0x57, 0x59, 0xb3,
|
||||
0x9e, 0xc5, 0xe5, 0xfc, 0xb8, 0x03, 0x8d, 0x79, 0x3d, 0x5f, 0x9b, 0xa8,
|
||||
0xb5, 0xb1, 0x0b, 0x70, 0x5f, 0x38, 0x3c, 0x4c, 0x86, 0x91, 0xc7, 0xbe,
|
||||
0x2f, 0xd8, 0xc1, 0x23, 0x66, 0x0e, 0x98, 0x65, 0xe1, 0x4f, 0x19, 0xdf,
|
||||
0xfb, 0xb7, 0xff, 0x38, 0x08, 0xc9, 0xf2, 0x04, 0xe7, 0x97, 0xd0, 0x6d,
|
||||
0xd8, 0x33, 0x3a, 0xc5, 0x83, 0x86, 0xee, 0x4e, 0xb6, 0x1e, 0x20, 0xec,
|
||||
0xa7, 0xef, 0x38, 0xd5, 0xb0, 0x5e, 0xb1, 0x15, 0x96, 0x6a, 0x5a, 0x89,
|
||||
0xad, 0x58, 0xa5, 0x00, 0x01, 0x00, 0x01, 0x42, 0x08, 0x65, 0x73, 0x53,
|
||||
0x44, 0x49, 0x60, 0x00, 0x06
|
||||
};
|
||||
|
||||
/**
|
||||
* Root CA card key reference
|
||||
*/
|
||||
|
@ -185,11 +250,22 @@ static u8 cvc_intca_keyref[] =
|
|||
static u8 cvc_ifd_keyref[] =
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
|
||||
|
||||
/**
|
||||
* In memory key reference for selecting IFD sent certificate in PIN channel DNIe 3.0
|
||||
*/
|
||||
static u8 cvc_ifd_keyref_pin[] =
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||||
|
||||
/**
|
||||
* Serial number for IFD Terminal application
|
||||
*/
|
||||
static u8 sn_ifd[] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
|
||||
|
||||
/**
|
||||
* Serial number for IFD Terminal application in PIN channel DNIe 3.0
|
||||
*/
|
||||
static u8 sn_ifd_pin[] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||||
|
||||
/**
|
||||
* Serial number for ICC card.
|
||||
* This buffer is to be filled at runtime
|
||||
|
@ -426,19 +502,46 @@ static int dnie_get_cvc_ifd_cert(sc_card_t * card, u8 ** cert, size_t * length)
|
|||
}
|
||||
|
||||
/**
|
||||
* Get IFD (Terminal) private key data.
|
||||
* Retrieve IFD (application) CVC certificate and length for
|
||||
* the PIN channel.
|
||||
*
|
||||
* As this is a local (in memory) provider, just get data specified in
|
||||
* DNIe's manual and compose an OpenSSL private key structure
|
||||
* Returns a byte array with the application's certificate
|
||||
* (in CardVerifiable Certificate format) to be sent to the
|
||||
* card in External Authentication process
|
||||
* As this is local provider, just points to provided static data,
|
||||
* and allways return success
|
||||
*
|
||||
* Notice that resulting data should be keept in memory as little as possible
|
||||
* Erasing them once used
|
||||
* @param card Pointer to card driver Certificate
|
||||
* @param cert Where to store resulting byte array
|
||||
* @param length len of returned byte array
|
||||
* @return SC_SUCCESS if ok; else error code
|
||||
*/
|
||||
static int dnie_get_cvc_ifd_cert_pin(sc_card_t * card, u8 ** cert, size_t * length)
|
||||
{
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
*cert = C_CV_IFDUser_AUT_pin_cert;
|
||||
*length = sizeof(C_CV_IFDUser_AUT_pin_cert);
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IFD (Terminal) private key data passing the three
|
||||
* arguments (modulus, public and private exponent).
|
||||
*
|
||||
* @param card pointer to card driver structure
|
||||
* @param ifd_privkey where to store IFD private key
|
||||
* @param modulus the byte array used as the modulus of the key
|
||||
* @param modulus_len the length of the modulus
|
||||
* @param public_exponent the byte array for the public exponent
|
||||
* @param public_exponent_len the length of the public exponent
|
||||
* @param private_exponent the byte array for the private exponent
|
||||
* @param private_exponent_len the length of the private exponent
|
||||
* @return SC_SUCCESS if ok; else error code
|
||||
*/
|
||||
static int dnie_get_ifd_privkey(sc_card_t * card, EVP_PKEY ** ifd_privkey)
|
||||
static int dnie_get_privkey(sc_card_t * card, EVP_PKEY ** ifd_privkey,
|
||||
u8 * modulus, int modulus_len,
|
||||
u8 * public_exponent, int public_exponent_len,
|
||||
u8 * private_exponent, int private_exponent_len)
|
||||
{
|
||||
RSA *ifd_rsa=NULL;
|
||||
BIGNUM *ifd_rsa_n, *ifd_rsa_e, *ifd_rsa_d = NULL;
|
||||
|
@ -476,6 +579,40 @@ static int dnie_get_ifd_privkey(sc_card_t * card, EVP_PKEY ** ifd_privkey)
|
|||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IFD (Terminal) private key data
|
||||
*
|
||||
* As this is a local (in memory) provider, just get data specified in
|
||||
* DNIe's manual and compose an OpenSSL private key structure
|
||||
*
|
||||
* @param card pointer to card driver structure
|
||||
* @param ifd_privkey where to store IFD private key
|
||||
* @return SC_SUCCESS if ok; else error code
|
||||
*/
|
||||
static int dnie_get_ifd_privkey(sc_card_t * card, EVP_PKEY ** ifd_privkey)
|
||||
{
|
||||
return dnie_get_privkey(card, ifd_privkey, ifd_modulus, sizeof(ifd_modulus),
|
||||
ifd_public_exponent, sizeof(ifd_public_exponent),
|
||||
ifd_private_exponent, sizeof(ifd_private_exponent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IFD (Terminal) private key data for the PIN channel DNIe 3.0
|
||||
*
|
||||
* As this is a local (in memory) provider, just get data specified in
|
||||
* DNIe's manual and compose an OpenSSL private key structure
|
||||
*
|
||||
* @param card pointer to card driver structure
|
||||
* @param ifd_privkey where to store IFD private key
|
||||
* @return SC_SUCCESS if ok; else error code
|
||||
*/
|
||||
static int dnie_get_ifd_privkey_pin(sc_card_t * card, EVP_PKEY ** ifd_privkey)
|
||||
{
|
||||
return dnie_get_privkey(card, ifd_privkey, ifd_pin_modulus, sizeof(ifd_pin_modulus),
|
||||
ifd_pin_public_exponent, sizeof(ifd_pin_public_exponent),
|
||||
ifd_pin_private_exponent, sizeof(ifd_pin_private_exponent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ICC intermediate CA Certificate from card.
|
||||
*
|
||||
|
@ -555,6 +692,26 @@ static int dnie_get_ifd_pubkey_ref(sc_card_t * card, u8 ** buf, size_t * len)
|
|||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve public key reference for IFD certificate for the PIN channel.
|
||||
*
|
||||
* This tells the card with in memory key reference is to be used
|
||||
* when CVC cert is sent for external auth procedure
|
||||
* As this driver is for local SM authentication SC_SUCCESS is allways returned
|
||||
*
|
||||
* @param card pointer to card driver structure
|
||||
* @param buf where to store data to be sent
|
||||
* @param len where to store data length
|
||||
* @return SC_SUCCESS if ok; else error code
|
||||
*/
|
||||
static int dnie_get_ifd_pubkey_ref_pin(sc_card_t * card, u8 ** buf, size_t * len)
|
||||
{
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
*buf = cvc_ifd_keyref_pin;
|
||||
*len = sizeof(cvc_ifd_keyref_pin);
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve key reference for ICC privkey.
|
||||
*
|
||||
|
@ -589,6 +746,24 @@ static int dnie_get_sn_ifd(sc_card_t * card, u8 ** buf)
|
|||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve SN.IFD (8 bytes left padded with zeroes if required)
|
||||
* for the PIN channel DNIe 3.0.
|
||||
*
|
||||
* In DNIe local SM procedure, just read it from static data and
|
||||
* return SC_SUCCESS
|
||||
*
|
||||
* @param card pointer to card structure
|
||||
* @param buf where to store result (8 bytes)
|
||||
* @return SC_SUCCESS if ok; else error
|
||||
*/
|
||||
static int dnie_get_sn_ifd_pin(sc_card_t * card, u8 ** buf)
|
||||
{
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
*buf = sn_ifd_pin;
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
/* Retrieve SN.ICC (8 bytes left padded with zeroes if needed).
|
||||
*
|
||||
* As DNIe reads serial number at startup, no need to read again
|
||||
|
@ -639,6 +814,10 @@ static int dnie_create_pre_ops(sc_card_t * card, cwa_provider_t * provider)
|
|||
return sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in DNIe the channel mode is changed to SM_MODE_TRANSMIT
|
||||
* after CWA initialization to be consistent with OpenSC
|
||||
*/
|
||||
static int dnie_create_post_ops(sc_card_t * card, cwa_provider_t * provider)
|
||||
{
|
||||
card->sm_ctx.sm_mode = SM_MODE_TRANSMIT;
|
||||
|
@ -705,6 +884,40 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card)
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the provider to use the common secure (DNIe 2.0)
|
||||
* channel.
|
||||
*
|
||||
* @param card the card to change the cwa provider for
|
||||
*/
|
||||
void dnie_change_cwa_provider_to_secure(sc_card_t * card)
|
||||
{
|
||||
cwa_provider_t * res = GET_DNIE_PRIV_DATA(card)->cwa_provider;
|
||||
|
||||
/* redefine different IFD data for secure channel */
|
||||
res->cwa_get_cvc_ifd_cert = dnie_get_cvc_ifd_cert;
|
||||
res->cwa_get_ifd_privkey = dnie_get_ifd_privkey;
|
||||
res->cwa_get_ifd_pubkey_ref = dnie_get_ifd_pubkey_ref;
|
||||
res->cwa_get_sn_ifd = dnie_get_sn_ifd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the provider to use the new PIN (DNIe 3.0)
|
||||
* channel.
|
||||
*
|
||||
* @param card the card to change the cwa provider for
|
||||
*/
|
||||
void dnie_change_cwa_provider_to_pin(sc_card_t * card)
|
||||
{
|
||||
cwa_provider_t * res = GET_DNIE_PRIV_DATA(card)->cwa_provider;
|
||||
|
||||
/* redefine different IFD data for PIN channel */
|
||||
res->cwa_get_cvc_ifd_cert = dnie_get_cvc_ifd_cert_pin;
|
||||
res->cwa_get_ifd_privkey = dnie_get_ifd_privkey_pin;
|
||||
res->cwa_get_ifd_pubkey_ref = dnie_get_ifd_pubkey_ref_pin;
|
||||
res->cwa_get_sn_ifd = dnie_get_sn_ifd_pin;
|
||||
}
|
||||
|
||||
int dnie_transmit_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
||||
{
|
||||
int res = SC_SUCCESS;
|
||||
|
|
|
@ -61,6 +61,14 @@ struct cwa_provider_st;
|
|||
#define GET_DNIE_PRIV_DATA(card) ((dnie_private_data_t *) ((card)->drv_data))
|
||||
#define GET_DNIE_UI_CTX(card) (((dnie_private_data_t *) ((card)->drv_data))->ui_ctx)
|
||||
|
||||
#define DNIE_30_VERSION 0x04
|
||||
|
||||
cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card);
|
||||
|
||||
void dnie_change_cwa_provider_to_pin(sc_card_t * card);
|
||||
|
||||
void dnie_change_cwa_provider_to_secure(sc_card_t * card);
|
||||
|
||||
int dnie_transmit_apdu(sc_card_t * card, sc_apdu_t * apdu);
|
||||
|
||||
void dnie_format_apdu(sc_card_t *card, sc_apdu_t *apdu,
|
||||
|
|
|
@ -41,9 +41,10 @@
|
|||
#include <openssl/x509.h>
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/rand.h>
|
||||
#include "cwa14890.h"
|
||||
#include "cwa-dnie.h"
|
||||
|
||||
#include "cwa14890.h"
|
||||
#define MAX_RESP_BUFFER_SIZE 2048
|
||||
|
||||
/**
|
||||
* Structure used to compose BER-TLV encoded data
|
||||
|
@ -435,6 +436,7 @@ static int cwa_verify_cvc_certificate(sc_card_t * card,
|
|||
sc_apdu_t apdu;
|
||||
int result = SC_SUCCESS;
|
||||
sc_context_t *ctx = NULL;
|
||||
u8 resp[MAX_RESP_BUFFER_SIZE];
|
||||
|
||||
/* safety check */
|
||||
if (!card || !card->ctx)
|
||||
|
@ -445,8 +447,8 @@ static int cwa_verify_cvc_certificate(sc_card_t * card,
|
|||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
/* compose apdu for Perform Security Operation (Verify cert) cmd */
|
||||
dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x00, 0xAE, 0, len,
|
||||
NULL, 0, cert, len);
|
||||
dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x00, 0xAE, 255, len,
|
||||
resp, MAX_RESP_BUFFER_SIZE, cert, len);
|
||||
|
||||
/* send composed apdu and parse result */
|
||||
result = dnie_transmit_apdu(card, &apdu);
|
||||
|
@ -475,6 +477,7 @@ static int cwa_set_security_env(sc_card_t * card,
|
|||
sc_apdu_t apdu;
|
||||
int result = SC_SUCCESS;
|
||||
sc_context_t *ctx = NULL;
|
||||
u8 resp[MAX_RESP_BUFFER_SIZE];
|
||||
|
||||
/* safety check */
|
||||
if (!card || !card->ctx)
|
||||
|
@ -485,8 +488,8 @@ static int cwa_set_security_env(sc_card_t * card,
|
|||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
/* compose apdu for Manage Security Environment cmd */
|
||||
dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, p1, p2, 0, length,
|
||||
NULL, 0, buffer, length);
|
||||
dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x22, p1, p2, 255, length,
|
||||
resp, MAX_RESP_BUFFER_SIZE, buffer, length);
|
||||
|
||||
/* send composed apdu and parse result */
|
||||
result = dnie_transmit_apdu(card, &apdu);
|
||||
|
@ -721,6 +724,7 @@ static int cwa_external_auth(sc_card_t * card, cwa_sm_status_t * sm)
|
|||
sc_apdu_t apdu;
|
||||
int result = SC_SUCCESS;
|
||||
sc_context_t *ctx = NULL;
|
||||
u8 resp[MAX_RESP_BUFFER_SIZE];
|
||||
|
||||
/* safety check */
|
||||
if (!card || !card->ctx)
|
||||
|
@ -730,7 +734,7 @@ static int cwa_external_auth(sc_card_t * card, cwa_sm_status_t * sm)
|
|||
|
||||
/* compose apdu for External Authenticate cmd */
|
||||
dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x82, 0x00, 0x00, 0, sizeof(sm->sig),
|
||||
NULL, 0, sm->sig, sizeof(sm->sig));
|
||||
resp, MAX_RESP_BUFFER_SIZE, sm->sig, sizeof(sm->sig));
|
||||
|
||||
/* send composed apdu and parse result */
|
||||
result = dnie_transmit_apdu(card, &apdu);
|
||||
|
@ -1081,7 +1085,15 @@ int cwa_create_secure_channel(sc_card_t * card,
|
|||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
case CWA_SM_COLD: /* force sm initialization process */
|
||||
sc_log(ctx, "CWA SM initialization requested");
|
||||
sc_log(ctx, "CWA SM initialization requested => reset and re-initialize");
|
||||
sc_reset(card, 0);
|
||||
provider->status.session.state = CWA_SM_INPROGRESS;
|
||||
break;
|
||||
case CWA_SM_OVER: /* create another channel over an existing one */
|
||||
if (provider->status.session.state != CWA_SM_ACTIVE) {
|
||||
sc_log(ctx, "CWA SM over requested => not in active state");
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_INVALID_LEVEL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc_log(ctx, "Invalid provided SM initialization flag");
|
||||
|
@ -1090,13 +1102,6 @@ int cwa_create_secure_channel(sc_card_t * card,
|
|||
|
||||
/* OK: lets start process */
|
||||
|
||||
/* reset card (warm reset, do not unpower card) */
|
||||
sc_log(ctx, "Resseting card");
|
||||
sc_reset(card, 0);
|
||||
|
||||
/* mark SM status as in progress */
|
||||
provider->status.session.state = CWA_SM_INPROGRESS;
|
||||
|
||||
/* call provider pre-operation method */
|
||||
sc_log(ctx, "CreateSecureChannel pre-operations");
|
||||
if (provider->cwa_create_pre_ops) {
|
||||
|
@ -1421,7 +1426,7 @@ int cwa_encode_apdu(sc_card_t * card,
|
|||
cwa_provider_t * provider, sc_apdu_t * from, sc_apdu_t * to)
|
||||
{
|
||||
u8 *apdubuf = NULL; /* to store resulting apdu */
|
||||
size_t apdulen;
|
||||
size_t apdulen, tlv_len;
|
||||
u8 *ccbuf = NULL; /* where to store data to eval cryptographic checksum CC */
|
||||
size_t cclen = 0;
|
||||
u8 macbuf[8]; /* to store and compute CC */
|
||||
|
@ -1529,13 +1534,17 @@ int cwa_encode_apdu(sc_card_t * card,
|
|||
msg = "Error in compose tag 8x87 TLV";
|
||||
goto encode_end;
|
||||
}
|
||||
}
|
||||
} else if ((0xff & from->le) > 0) {
|
||||
|
||||
/* if le byte is declared, compose and add Le TLV */
|
||||
/* FIXME: For DNIe we must not send the le bytes
|
||||
when le == 256 but this goes against the standard
|
||||
and might break other cards reusing this code */
|
||||
if ((0xff & from->le) > 0) {
|
||||
/* NOTE: In FNMT MultiPKCS11 code this is an if, i.e.,
|
||||
the le is only sent if no data (lc) is set.
|
||||
In DNIe 3.0 pin verification sending both TLV return
|
||||
69 88 "SM Data Object incorrect". For the moment it is
|
||||
fixed sendind le=0 in pin verification apdu */
|
||||
u8 le = 0xff & from->le;
|
||||
res = cwa_compose_tlv(card, 0x97, 1, &le, &ccbuf, &cclen);
|
||||
if (res != SC_SUCCESS) {
|
||||
|
@ -1574,7 +1583,9 @@ int cwa_encode_apdu(sc_card_t * card,
|
|||
&k1, &k2, DES_ENCRYPT);
|
||||
|
||||
/* compose and add computed MAC TLV to result buffer */
|
||||
res = cwa_compose_tlv(card, 0x8E, 4, macbuf, &apdubuf, &apdulen);
|
||||
tlv_len = (card->atr.value[15] >= DNIE_30_VERSION)? 8 : 4;
|
||||
sc_log(ctx, "Using TLV lenght: %d", tlv_len);
|
||||
res = cwa_compose_tlv(card, 0x8E, tlv_len, macbuf, &apdubuf, &apdulen);
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Encode APDU compose_tlv(0x87) failed";
|
||||
goto encode_end;
|
||||
|
@ -1620,7 +1631,7 @@ int cwa_decode_response(sc_card_t * card,
|
|||
cwa_provider_t * provider,
|
||||
sc_apdu_t * apdu)
|
||||
{
|
||||
size_t i, j;
|
||||
size_t i, j, tlv_len;
|
||||
cwa_tlv_t tlv_array[4];
|
||||
cwa_tlv_t *p_tlv = &tlv_array[0]; /* to store plain data (Tag 0x81) */
|
||||
cwa_tlv_t *e_tlv = &tlv_array[1]; /* to store pad encoded data (Tag 0x87) */
|
||||
|
@ -1706,7 +1717,8 @@ int cwa_decode_response(sc_card_t * card,
|
|||
res = SC_ERROR_INVALID_DATA;
|
||||
goto response_decode_end;
|
||||
}
|
||||
if (m_tlv->len != 4) {
|
||||
tlv_len = (card->atr.value[15] >= DNIE_30_VERSION)? 8 : 4;
|
||||
if (m_tlv->len != tlv_len) {
|
||||
msg = "Invalid MAC TAG Length";
|
||||
res = SC_ERROR_INVALID_DATA;
|
||||
goto response_decode_end;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#define CWA_SM_OFF 0x00 /** Disable SM channel */
|
||||
#define CWA_SM_COLD 0x01 /** force creation of a new SM channel */
|
||||
#define CWA_SM_WARM 0x02 /** Create new SM channel only if state is NONE */
|
||||
#define CWA_SM_OVER 0x03 /** Create new SM channel only over another channel */
|
||||
|
||||
/* TAGS for encoded APDU's */
|
||||
#define CWA_SM_PLAIN_TAG 0x81 /** Plain value (to be protected by CC) */
|
||||
|
|
Loading…
Reference in New Issue