OpenPGP: implement pgp_put_data()
This commit is contained in:
parent
a1ed22b6fd
commit
3ac834e277
|
@ -1014,7 +1014,70 @@ pgp_do_iswritable(sc_card_t *card, unsigned int tag, struct blob **ref_blob)
|
|||
static int
|
||||
pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
|
||||
{
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
sc_apdu_t apdu;
|
||||
struct pgp_priv_data *priv = DRVDATA(card);
|
||||
struct blob *affected_blob = NULL;
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
/* Check if the tag is writable */
|
||||
if (!pgp_do_iswritable(card, tag, &affected_blob)) {
|
||||
sc_log(card->ctx, "The %04X DO is not writable.", tag);
|
||||
return SC_ERROR_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
/* Build APDU */
|
||||
if (buf_len > 0xFF && card->caps & SC_CARD_CAP_APDU_EXT) {
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_EXT, 0xDA, tag >> 8, tag);
|
||||
}
|
||||
else {
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDA, tag >> 8, tag);
|
||||
/* In short APDU, the Lc only takes 1 byte */
|
||||
apdu.lc = ((buf_len > 0xFF) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 0xFF : buf_len;
|
||||
}
|
||||
/* TODO:
|
||||
* Command chaining for the large data.
|
||||
**/
|
||||
apdu.data = buf;
|
||||
apdu.datalen = buf_len;
|
||||
apdu.lc = buf_len;
|
||||
|
||||
if (buf == NULL && buf_len == 0) {
|
||||
/* Erase DO content.
|
||||
*
|
||||
* We won't call sc_transmit_apdu() in order to bypass
|
||||
* the check of APDU, because sc_transmit_apdu() does not allow
|
||||
* null data. */
|
||||
r = sc_lock(card); /* acquire card lock*/
|
||||
sc_log(card->ctx, "card->reader->ops->transmit");
|
||||
r = card->reader->ops->transmit(card->reader, &apdu);
|
||||
/* all done => release lock */
|
||||
if (sc_unlock(card) != SC_SUCCESS)
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "sc_unlock failed");
|
||||
|
||||
return r;
|
||||
}
|
||||
/* Send APDU to card */
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
/* Check response */
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
|
||||
/* Instruct more in case of error */
|
||||
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Please verify PIN first.");
|
||||
}
|
||||
LOG_TEST_RET(card->ctx, r, "Card returned error");
|
||||
|
||||
/* Update the corresponding file */
|
||||
sc_log(card->ctx, "To update the corresponding blob data");
|
||||
r = pgp_set_blob(affected_blob, buf, buf_len);
|
||||
if (r < 0)
|
||||
sc_log(card->ctx, "Failed to update the blob %04X. Error %d.", affected_blob->id, r);
|
||||
/* The pgp_update_tag_blob()'s failure won't affect */
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, buf_len);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue