mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
scd:p15: Improve support for some CardOS based cards.
* scd/iso7816.c (iso7816_read_binary_ext): Add optional arg r_sw and change callers. (iso7816_read_record): Factor all code out to ... (iso7816_read_record_ext): new. * scd/app-p15.c (select_and_read_binary): Fallback to record reading. (read_ef_aodf): Clear EOF error.
This commit is contained in:
parent
60e1ce6612
commit
c7b9a4ee43
@ -466,6 +466,7 @@ select_and_read_binary (int slot, unsigned short efid, const char *efid_desc,
|
|||||||
unsigned char **buffer, size_t *buflen)
|
unsigned char **buffer, size_t *buflen)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
|
int sw;
|
||||||
|
|
||||||
err = iso7816_select_file (slot, efid, 0);
|
err = iso7816_select_file (slot, efid, 0);
|
||||||
if (err)
|
if (err)
|
||||||
@ -474,11 +475,33 @@ select_and_read_binary (int slot, unsigned short efid, const char *efid_desc,
|
|||||||
efid_desc, efid, gpg_strerror (err));
|
efid_desc, efid, gpg_strerror (err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
err = iso7816_read_binary (slot, 0, 0, buffer, buflen);
|
|
||||||
if (err)
|
err = iso7816_read_binary_ext (slot, 0, 0, 0, buffer, buflen, &sw);
|
||||||
|
if (err && sw == 0x6981)
|
||||||
{
|
{
|
||||||
log_error ("p15: error reading %s (0x%04X): %s\n",
|
/* Command was not possible for file structure. Try to read the
|
||||||
efid_desc, efid, gpg_strerror (err));
|
* first record instead. */
|
||||||
|
err = iso7816_read_record_ext (slot, 1, 1, 0, buffer, buflen, &sw);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("p15: error reading %s (0x%04X)"
|
||||||
|
" after fallback to record mode: %s (sw=%04X)\n",
|
||||||
|
efid_desc, efid, gpg_strerror (err), sw);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
/* On a CardOS based card I noticed that the record started with
|
||||||
|
* a byte 0x01 followed by another byte with the length of the
|
||||||
|
* record. Detect this here and remove this prefix. */
|
||||||
|
if (*buflen > 2 && (*buffer)[0] == 1 && (*buffer)[1] == *buflen - 2)
|
||||||
|
{
|
||||||
|
memmove (*buffer, *buffer + 2, *buflen - 2);
|
||||||
|
*buflen = *buflen - 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (err)
|
||||||
|
{
|
||||||
|
log_error ("p15: error reading %s (0x%04X): %s (sw=%04X)\n",
|
||||||
|
efid_desc, efid, gpg_strerror (err), sw);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -2180,6 +2203,8 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
|
|||||||
extensions of pkcs#15. */
|
extensions of pkcs#15. */
|
||||||
|
|
||||||
ready:
|
ready:
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_EOF)
|
||||||
|
err = 0;
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
{
|
{
|
||||||
log_info ("p15: AODF %04hX: id=", fid);
|
log_info ("p15: AODF %04hX: id=", fid);
|
||||||
@ -2922,7 +2947,7 @@ readcert_by_cdf (app_t app, cdf_object_t cdf,
|
|||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
err = iso7816_read_binary_ext (app_get_slot (app), 1, cdf->off, cdf->len,
|
err = iso7816_read_binary_ext (app_get_slot (app), 1, cdf->off, cdf->len,
|
||||||
&buffer, &buflen);
|
&buffer, &buflen, NULL);
|
||||||
if (!err && (!buflen || *buffer == 0xff))
|
if (!err && (!buflen || *buffer == 0xff))
|
||||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -875,13 +875,15 @@ iso7816_get_challenge (int slot, int length, unsigned char *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Perform a READ BINARY command requesting a maximum of NMAX bytes
|
/* Perform a READ BINARY command requesting a maximum of NMAX bytes
|
||||||
from OFFSET. With NMAX = 0 the entire file is read. The result is
|
* from OFFSET. With NMAX = 0 the entire file is read. The result is
|
||||||
stored in a newly allocated buffer at the address passed by RESULT.
|
* stored in a newly allocated buffer at the address passed by RESULT.
|
||||||
Returns the length of this data at the address of RESULTLEN. */
|
* Returns the length of this data at the address of RESULTLEN. If
|
||||||
|
* R_SW is not NULL the last status word is stored there. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
iso7816_read_binary_ext (int slot, int extended_mode,
|
iso7816_read_binary_ext (int slot, int extended_mode,
|
||||||
size_t offset, size_t nmax,
|
size_t offset, size_t nmax,
|
||||||
unsigned char **result, size_t *resultlen)
|
unsigned char **result, size_t *resultlen,
|
||||||
|
int *r_sw)
|
||||||
{
|
{
|
||||||
int sw;
|
int sw;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
@ -889,6 +891,9 @@ iso7816_read_binary_ext (int slot, int extended_mode,
|
|||||||
int read_all = !nmax;
|
int read_all = !nmax;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
|
if (r_sw)
|
||||||
|
*r_sw = 0;
|
||||||
|
|
||||||
if (!result || !resultlen)
|
if (!result || !resultlen)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
@ -914,6 +919,8 @@ iso7816_read_binary_ext (int slot, int extended_mode,
|
|||||||
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
|
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
|
||||||
n, &buffer, &bufferlen);
|
n, &buffer, &bufferlen);
|
||||||
}
|
}
|
||||||
|
if (r_sw)
|
||||||
|
*r_sw = sw;
|
||||||
|
|
||||||
if (*result && sw == SW_BAD_P0_P1)
|
if (*result && sw == SW_BAD_P0_P1)
|
||||||
{
|
{
|
||||||
@ -974,7 +981,8 @@ gpg_error_t
|
|||||||
iso7816_read_binary (int slot, size_t offset, size_t nmax,
|
iso7816_read_binary (int slot, size_t offset, size_t nmax,
|
||||||
unsigned char **result, size_t *resultlen)
|
unsigned char **result, size_t *resultlen)
|
||||||
{
|
{
|
||||||
return iso7816_read_binary_ext (slot, 0, offset, nmax, result, resultlen);
|
return iso7816_read_binary_ext (slot, 0, offset, nmax,
|
||||||
|
result, resultlen, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -984,15 +992,20 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax,
|
|||||||
should be 0 to read the current EF or contain a short EF. The
|
should be 0 to read the current EF or contain a short EF. The
|
||||||
result is stored in a newly allocated buffer at the address passed
|
result is stored in a newly allocated buffer at the address passed
|
||||||
by RESULT. Returns the length of this data at the address of
|
by RESULT. Returns the length of this data at the address of
|
||||||
RESULTLEN. */
|
RESULTLEN. If R_SW is not NULL the last status word is stored
|
||||||
|
there. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
iso7816_read_record (int slot, int recno, int reccount, int short_ef,
|
iso7816_read_record_ext (int slot, int recno, int reccount, int short_ef,
|
||||||
unsigned char **result, size_t *resultlen)
|
unsigned char **result, size_t *resultlen,
|
||||||
|
int *r_sw)
|
||||||
{
|
{
|
||||||
int sw;
|
int sw;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
size_t bufferlen;
|
size_t bufferlen;
|
||||||
|
|
||||||
|
if (r_sw)
|
||||||
|
*r_sw = 0;
|
||||||
|
|
||||||
if (!result || !resultlen)
|
if (!result || !resultlen)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
@ -1011,6 +1024,8 @@ iso7816_read_record (int slot, int recno, int reccount, int short_ef,
|
|||||||
short_ef? short_ef : 0x04,
|
short_ef? short_ef : 0x04,
|
||||||
-1, NULL,
|
-1, NULL,
|
||||||
0, &buffer, &bufferlen);
|
0, &buffer, &bufferlen);
|
||||||
|
if (r_sw)
|
||||||
|
*r_sw = sw;
|
||||||
|
|
||||||
if (sw != SW_SUCCESS && sw != SW_EOF_REACHED)
|
if (sw != SW_SUCCESS && sw != SW_EOF_REACHED)
|
||||||
{
|
{
|
||||||
@ -1028,6 +1043,15 @@ iso7816_read_record (int slot, int recno, int reccount, int short_ef,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpg_error_t
|
||||||
|
iso7816_read_record (int slot, int recno, int reccount, int short_ef,
|
||||||
|
unsigned char **result, size_t *resultlen)
|
||||||
|
{
|
||||||
|
return iso7816_read_record_ext (slot, recno, reccount, short_ef,
|
||||||
|
result, resultlen, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Perform an UPDATE BINARY command on card in SLOT. Write DATA of
|
/* Perform an UPDATE BINARY command on card in SLOT. Write DATA of
|
||||||
* length DATALEN to a transparent file at OFFSET. */
|
* length DATALEN to a transparent file at OFFSET. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
|
@ -142,9 +142,14 @@ gpg_error_t iso7816_get_challenge (int slot,
|
|||||||
|
|
||||||
gpg_error_t iso7816_read_binary_ext (int slot, int extended_mode,
|
gpg_error_t iso7816_read_binary_ext (int slot, int extended_mode,
|
||||||
size_t offset, size_t nmax,
|
size_t offset, size_t nmax,
|
||||||
unsigned char **result, size_t *resultlen);
|
unsigned char **result, size_t *resultlen,
|
||||||
|
int *r_sw);
|
||||||
gpg_error_t iso7816_read_binary (int slot, size_t offset, size_t nmax,
|
gpg_error_t iso7816_read_binary (int slot, size_t offset, size_t nmax,
|
||||||
unsigned char **result, size_t *resultlen);
|
unsigned char **result, size_t *resultlen);
|
||||||
|
gpg_error_t iso7816_read_record_ext (int slot, int recno, int reccount,
|
||||||
|
int short_ef,
|
||||||
|
unsigned char **result, size_t *resultlen,
|
||||||
|
int *r_sw);
|
||||||
gpg_error_t iso7816_read_record (int slot, int recno, int reccount,
|
gpg_error_t iso7816_read_record (int slot, int recno, int reccount,
|
||||||
int short_ef,
|
int short_ef,
|
||||||
unsigned char **result, size_t *resultlen);
|
unsigned char **result, size_t *resultlen);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user