- try to deal with RSA_SIG keys (first try RSA_PURE_SIG, then RSA_SIG)
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1258 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
901a2d90e3
commit
c2e40211be
|
@ -595,34 +595,32 @@ etoken_set_security_env(struct sc_card *card,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute digital signature
|
* Compute digital signature
|
||||||
* Note we assume that the key algorithm used here is RSA_PURE_SIG
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* internal function to do the actual signature computation */
|
||||||
static int
|
static int
|
||||||
etoken_compute_signature(struct sc_card *card,
|
do_compute_signature(struct sc_card *card, const u8 *data, size_t datalen,
|
||||||
const u8 *data, size_t datalen,
|
u8 *out, size_t outlen)
|
||||||
u8 *out, size_t outlen)
|
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
struct sc_apdu apdu;
|
struct sc_apdu apdu;
|
||||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
|
||||||
assert(card != NULL && data != NULL && out != NULL);
|
if (datalen > SC_MAX_APDU_BUFFER_SIZE ||
|
||||||
if (datalen > 255)
|
outlen > SC_MAX_APDU_BUFFER_SIZE)
|
||||||
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
|
return SC_ERROR_INTERNAL;
|
||||||
if (outlen < datalen)
|
|
||||||
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_BUFFER_TOO_SMALL);
|
|
||||||
|
|
||||||
/* INS: 0x2A PERFORM SECURITY OPERATION
|
/* INS: 0x2A PERFORM SECURITY OPERATION
|
||||||
* P1: 0x9E Resp: Digital Signature
|
* P1: 0x9E Resp: Digital Signature
|
||||||
* P2: 0x9A Cmd: Input for Digital Signature */
|
* P2: 0x9A Cmd: Input for Digital Signature */
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A);
|
||||||
apdu.resp = out;
|
apdu.resp = rbuf;
|
||||||
apdu.le = datalen;
|
apdu.le = outlen;
|
||||||
apdu.resplen = sizeof(rbuf);
|
apdu.resplen = sizeof(rbuf);
|
||||||
|
|
||||||
memcpy(sbuf, data, datalen);
|
memcpy(sbuf, data, datalen);
|
||||||
apdu.data = data;
|
apdu.data = sbuf;
|
||||||
apdu.lc = datalen;
|
apdu.lc = datalen;
|
||||||
apdu.datalen = datalen;
|
apdu.datalen = datalen;
|
||||||
apdu.sensitive = 1;
|
apdu.sensitive = 1;
|
||||||
|
@ -630,12 +628,62 @@ etoken_compute_signature(struct sc_card *card,
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
|
||||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||||
|
memcpy(out, rbuf, outlen);
|
||||||
SC_FUNC_RETURN(card->ctx, 4, apdu.resplen);
|
SC_FUNC_RETURN(card->ctx, 4, apdu.resplen);
|
||||||
}
|
}
|
||||||
SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
etoken_compute_signature(struct sc_card *card, const u8 *data, size_t datalen,
|
||||||
|
u8 *out, size_t outlen)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
u8 buf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
size_t buf_len = sizeof(buf), tmp_len = buf_len;
|
||||||
|
struct sc_context *ctx;
|
||||||
|
|
||||||
|
assert(card != NULL && data != NULL && out != NULL);
|
||||||
|
ctx = card->ctx;
|
||||||
|
SC_FUNC_CALLED(ctx, 1);
|
||||||
|
|
||||||
|
if (datalen > 255)
|
||||||
|
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
if (outlen < datalen)
|
||||||
|
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_BUFFER_TOO_SMALL);
|
||||||
|
outlen = datalen;
|
||||||
|
|
||||||
|
/* XXX As we don't know what operations are allowed with a
|
||||||
|
* certain key, let's try RSA_PURE etc. and see which operation
|
||||||
|
* succeeds (this is not really beautiful, but currently the
|
||||||
|
* only way I see) -- Nils
|
||||||
|
*/
|
||||||
|
if (ctx->debug >= 3)
|
||||||
|
debug(ctx, "trying RSA_PURE_SIG (padded DigestInfo)\n");
|
||||||
|
r = do_compute_signature(card, data, datalen, out, outlen);
|
||||||
|
if (r >= SC_SUCCESS)
|
||||||
|
SC_FUNC_RETURN(ctx, 4, r);
|
||||||
|
if (ctx->debug >= 3)
|
||||||
|
debug(ctx, "trying RSA_SIG (just the DigestInfo)\n");
|
||||||
|
/* remove padding: first try pkcs1 bt01 padding */
|
||||||
|
r = sc_pkcs1_strip_01_padding(data, datalen, buf, &tmp_len);
|
||||||
|
if (r != SC_SUCCESS) {
|
||||||
|
/* no pkcs1 bt01 padding => let's try zero padding */
|
||||||
|
tmp_len = buf_len;
|
||||||
|
r = sc_strip_zero_padding(data, datalen, buf, &tmp_len);
|
||||||
|
if (r != SC_SUCCESS)
|
||||||
|
SC_FUNC_RETURN(ctx, 4, r);
|
||||||
|
}
|
||||||
|
r = do_compute_signature(card, buf, tmp_len, out, outlen);
|
||||||
|
if (r >= SC_SUCCESS)
|
||||||
|
SC_FUNC_RETURN(ctx, 4, r);
|
||||||
|
if (ctx->debug >= 3)
|
||||||
|
debug(ctx, "trying to sign raw hash value\n");
|
||||||
|
r = sc_pkcs1_strip_digest_info_prefix(NULL,buf,tmp_len,buf,&buf_len);
|
||||||
|
if (r != SC_SUCCESS)
|
||||||
|
SC_FUNC_RETURN(ctx, 4, r);
|
||||||
|
return do_compute_signature(card, buf, buf_len, out, outlen);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
etoken_lifecycle_get(struct sc_card *card, int *mode)
|
etoken_lifecycle_get(struct sc_card *card, int *mode)
|
||||||
|
|
Loading…
Reference in New Issue