iasecc: support the digital signature with RSA scheme PKCS#1 SHA-256 ...
in this mode the final digest (SHA-256) step has to be performed by card. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@5433 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
1f892af9eb
commit
1e025a0ded
|
@ -2734,64 +2734,101 @@ iasecc_decipher(struct sc_card *card,
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iasecc_get_qsign_data (struct sc_context *ctx, const unsigned char *in, size_t in_len,
|
iasecc_qsign_data_sha1(struct sc_context *ctx, const unsigned char *in, size_t in_len,
|
||||||
struct iasecc_qsign_data *out, unsigned hash_type)
|
struct iasecc_qsign_data *out)
|
||||||
{
|
{
|
||||||
SHA_CTX sha;
|
SHA_CTX sha;
|
||||||
SHA_LONG *hh[5] = {
|
SHA_LONG pre_hash_Nl, *hh[5] = {
|
||||||
&sha.h0, &sha.h1, &sha.h2, &sha.h3, &sha.h4
|
&sha.h0, &sha.h1, &sha.h2, &sha.h3, &sha.h4
|
||||||
};
|
};
|
||||||
int jj, ii;
|
int jj, ii;
|
||||||
int hh_size = sizeof(SHA_LONG), hh_num = SHA_DIGEST_LENGTH / sizeof(SHA_LONG);
|
int hh_size = sizeof(SHA_LONG), hh_num = SHA_DIGEST_LENGTH / sizeof(SHA_LONG);
|
||||||
unsigned long len;
|
|
||||||
|
|
||||||
LOG_FUNC_CALLED(ctx);
|
LOG_FUNC_CALLED(ctx);
|
||||||
if (hash_type != SC_ALGORITHM_RSA_HASH_SHA1)
|
sc_log(ctx, "sc_pkcs15_get_qsign_data() input data length %i", in_len);
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
|
||||||
|
|
||||||
SHA1_Init(&sha);
|
|
||||||
|
|
||||||
if (!in || !in_len || !out)
|
if (!in || !in_len || !out)
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
sc_log(ctx, "sc_pkcs15_get_qsign_data() input data length %i", in_len);
|
|
||||||
|
|
||||||
for (ii=0; ii<in_len; ) {
|
SHA1_Init(&sha);
|
||||||
len = in_len - ii > 64 ? 64 : in_len - ii;
|
SHA1_Update(&sha, in, in_len);
|
||||||
SHA1_Update(&sha, in + ii, len);
|
|
||||||
ii += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
sha.Nl -= sha.Nl % 0x200;
|
|
||||||
|
|
||||||
for (jj=0; jj<hh_num; jj++)
|
for (jj=0; jj<hh_num; jj++)
|
||||||
for(ii=0; ii<hh_size; ii++)
|
for(ii=0; ii<hh_size; ii++)
|
||||||
out->pre_hash[jj*hh_size + ii] = ((*hh[jj] >> 8*(hh_size-1-ii)) & 0xFF);
|
out->pre_hash[jj*hh_size + ii] = ((*hh[jj] >> 8*(hh_size-1-ii)) & 0xFF);
|
||||||
out->pre_hash_size = SHA_DIGEST_LENGTH;
|
out->pre_hash_size = SHA_DIGEST_LENGTH;
|
||||||
|
sc_log(ctx, "Pre SHA1:%s", sc_dump_hex(out->pre_hash, out->pre_hash_size));
|
||||||
|
|
||||||
|
pre_hash_Nl = sha.Nl - (sha.Nl % (sizeof(sha.data) * 8));
|
||||||
for (ii=0; ii<hh_size; ii++) {
|
for (ii=0; ii<hh_size; ii++) {
|
||||||
out->counter[ii] = (sha.Nh >> 8*(hh_size-1-ii)) &0xFF;
|
out->counter[ii] = (sha.Nh >> 8*(hh_size-1-ii)) &0xFF;
|
||||||
out->counter[hh_size+ii] = (sha.Nl >> 8*(hh_size-1-ii)) &0xFF;
|
out->counter[hh_size+ii] = (pre_hash_Nl >> 8*(hh_size-1-ii)) &0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ii=0, out->counter_long=0; ii<sizeof(out->counter); ii++)
|
for (ii=0, out->counter_long=0; ii<sizeof(out->counter); ii++)
|
||||||
out->counter_long = out->counter_long*0x100 + out->counter[ii];
|
out->counter_long = out->counter_long*0x100 + out->counter[ii];
|
||||||
|
|
||||||
sc_log(ctx, "Pre SHA1:%s", sc_dump_hex(out->pre_hash, out->pre_hash_size));
|
|
||||||
sc_log(ctx, "Pre counter(%li):%s", out->counter_long, sc_dump_hex(out->counter, sizeof(out->counter)));
|
sc_log(ctx, "Pre counter(%li):%s", out->counter_long, sc_dump_hex(out->counter, sizeof(out->counter)));
|
||||||
|
|
||||||
for (ii=0;ii<sha.num; ii++)
|
for (ii=0;ii<sha.num; ii++)
|
||||||
out->last_block[ii] = (sha.data[ii/hh_size] >> 8*(hh_size-1-(ii%hh_size))) &0xFF;
|
out->last_block[ii] = (sha.data[ii/hh_size] >> 8*(ii%hh_size)) &0xFF;
|
||||||
out->last_block_size = sha.num;
|
out->last_block_size = sha.num;
|
||||||
sc_log(ctx, "Last block(%i):%s", out->last_block_size, sc_dump_hex(out->last_block, out->last_block_size));
|
sc_log(ctx, "Last block(%i):%s", out->last_block_size, sc_dump_hex(out->last_block, out->last_block_size));
|
||||||
|
|
||||||
SHA1_Final(out->hash, &sha);
|
SHA1_Final(out->hash, &sha);
|
||||||
out->hash_size = SHA_DIGEST_LENGTH;
|
out->hash_size = SHA_DIGEST_LENGTH;
|
||||||
|
sc_log(ctx, "Expected digest %s\n", sc_dump_hex(out->hash, out->hash_size));
|
||||||
|
|
||||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
iasecc_qsign_data_sha256(struct sc_context *ctx, const unsigned char *in, size_t in_len,
|
||||||
|
struct iasecc_qsign_data *out)
|
||||||
|
{
|
||||||
|
SHA256_CTX sha256;
|
||||||
|
SHA_LONG pre_hash_Nl;
|
||||||
|
int jj, ii;
|
||||||
|
int hh_size = sizeof(SHA_LONG), hh_num = SHA256_DIGEST_LENGTH / sizeof(SHA_LONG);
|
||||||
|
|
||||||
|
LOG_FUNC_CALLED(ctx);
|
||||||
|
if (!in || !in_len || !out)
|
||||||
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
|
sc_log(ctx, "sc_pkcs15_get_qsign_data() input data length %i", in_len);
|
||||||
|
|
||||||
|
SHA256_Init(&sha256);
|
||||||
|
SHA256_Update(&sha256, in, in_len);
|
||||||
|
|
||||||
|
for (jj=0; jj<hh_num; jj++)
|
||||||
|
for(ii=0; ii<hh_size; ii++)
|
||||||
|
out->pre_hash[jj*hh_size + ii] = ((sha256.h[jj] >> 8*(hh_size-1-ii)) & 0xFF);
|
||||||
|
out->pre_hash_size = SHA256_DIGEST_LENGTH;
|
||||||
|
|
||||||
|
pre_hash_Nl = sha256.Nl - (sha256.Nl % (sizeof(sha256.data) * 8));
|
||||||
|
for (ii=0; ii<hh_size; ii++) {
|
||||||
|
out->counter[ii] = (sha256.Nh >> 8*(hh_size-1-ii)) &0xFF;
|
||||||
|
out->counter[hh_size+ii] = (pre_hash_Nl >> 8*(hh_size-1-ii)) &0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ii=0, out->counter_long=0; ii<sizeof(out->counter); ii++)
|
||||||
|
out->counter_long = out->counter_long*0x100 + out->counter[ii];
|
||||||
|
|
||||||
|
sc_log(ctx, "Pre hash:%s", sc_dump_hex(out->pre_hash, out->pre_hash_size));
|
||||||
|
sc_log(ctx, "Pre counter(%li):%s", out->counter_long, sc_dump_hex(out->counter, sizeof(out->counter)));
|
||||||
|
|
||||||
|
for (ii=0;ii<sha256.num; ii++)
|
||||||
|
out->last_block[ii] = (sha256.data[ii/hh_size] >> 8*(ii%hh_size)) &0xFF;
|
||||||
|
|
||||||
|
out->last_block_size = sha256.num;
|
||||||
|
sc_log(ctx, "Last block(%i):%s", out->last_block_size, sc_dump_hex(out->last_block, out->last_block_size));
|
||||||
|
|
||||||
|
SHA256_Final(out->hash, &sha256);
|
||||||
|
out->hash_size = SHA256_DIGEST_LENGTH;
|
||||||
|
sc_log(ctx, "Expected digest %s\n", sc_dump_hex(out->hash, out->hash_size));
|
||||||
|
|
||||||
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iasecc_compute_signature_dst(struct sc_card *card,
|
iasecc_compute_signature_dst(struct sc_card *card,
|
||||||
const unsigned char *in, size_t in_len, unsigned char *out, size_t out_len)
|
const unsigned char *in, size_t in_len, unsigned char *out, size_t out_len)
|
||||||
|
@ -2815,11 +2852,10 @@ iasecc_compute_signature_dst(struct sc_card *card,
|
||||||
|
|
||||||
memset(&qsign_data, 0, sizeof(qsign_data));
|
memset(&qsign_data, 0, sizeof(qsign_data));
|
||||||
if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) {
|
if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) {
|
||||||
rv = iasecc_get_qsign_data(card->ctx, in, in_len, &qsign_data, SC_ALGORITHM_RSA_HASH_SHA1);
|
rv = iasecc_qsign_data_sha1(card->ctx, in, in_len, &qsign_data);
|
||||||
}
|
}
|
||||||
else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) {
|
else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) {
|
||||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "RSA_HASH_SHA256 not yet supported");
|
rv = iasecc_qsign_data_sha256(card->ctx, in, in_len, &qsign_data);
|
||||||
rv = iasecc_get_qsign_data(card->ctx, in, in_len, &qsign_data, SC_ALGORITHM_RSA_HASH_SHA256);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Need RSA_HASH_SHA1 or RSA_HASH_SHA256 algorithm");
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Need RSA_HASH_SHA1 or RSA_HASH_SHA256 algorithm");
|
||||||
|
|
Loading…
Reference in New Issue