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:
vtarasov 2011-05-09 15:31:02 +00:00
parent 1f892af9eb
commit 1e025a0ded
1 changed files with 61 additions and 25 deletions

View File

@ -2734,64 +2734,101 @@ iasecc_decipher(struct sc_card *card,
static int
iasecc_get_qsign_data (struct sc_context *ctx, const unsigned char *in, size_t in_len,
struct iasecc_qsign_data *out, unsigned hash_type)
iasecc_qsign_data_sha1(struct sc_context *ctx, const unsigned char *in, size_t in_len,
struct iasecc_qsign_data *out)
{
SHA_CTX sha;
SHA_LONG *hh[5] = {
SHA_LONG pre_hash_Nl, *hh[5] = {
&sha.h0, &sha.h1, &sha.h2, &sha.h3, &sha.h4
};
int jj, ii;
int hh_size = sizeof(SHA_LONG), hh_num = SHA_DIGEST_LENGTH / sizeof(SHA_LONG);
unsigned long len;
LOG_FUNC_CALLED(ctx);
if (hash_type != SC_ALGORITHM_RSA_HASH_SHA1)
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
SHA1_Init(&sha);
sc_log(ctx, "sc_pkcs15_get_qsign_data() input data length %i", in_len);
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);
for (ii=0; ii<in_len; ) {
len = in_len - ii > 64 ? 64 : in_len - ii;
SHA1_Update(&sha, in + ii, len);
ii += len;
}
sha.Nl -= sha.Nl % 0x200;
SHA1_Init(&sha);
SHA1_Update(&sha, in, in_len);
for (jj=0; jj<hh_num; jj++)
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_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++) {
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++)
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)));
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;
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);
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);
}
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
iasecc_compute_signature_dst(struct sc_card *card,
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));
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) {
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "RSA_HASH_SHA256 not yet supported");
rv = iasecc_get_qsign_data(card->ctx, in, in_len, &qsign_data, SC_ALGORITHM_RSA_HASH_SHA256);
rv = iasecc_qsign_data_sha256(card->ctx, in, in_len, &qsign_data);
}
else
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Need RSA_HASH_SHA1 or RSA_HASH_SHA256 algorithm");