- Added X.509 algorithm id decoding and encoding to asn1.c

- Implemented a generic ATR matching helper function
- Made signing much smarter (should even work now)
- Added info about supported crypto algorithms to struct sc_card


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@276 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
jey 2002-03-08 05:59:57 +00:00
parent 7477cb3c01
commit 3416461c4b
17 changed files with 403 additions and 133 deletions

View File

@ -761,6 +761,46 @@ static int asn1_encode_p15_object(struct sc_context *ctx, const struct sc_asn1_p
return r;
}
static const struct sc_asn1_entry c_asn1_alg_id[6] = {
{ "algorithm", SC_ASN1_OBJECT, ASN1_OBJECT, 0, NULL },
{ "parameters", SC_ASN1_STRUCT, 0, SC_ASN1_OPTIONAL, NULL },
{ NULL }
};
static int asn1_decode_algorithm_id(struct sc_context *ctx, const u8 *in,
size_t len, struct sc_algorithm_id *id,
int depth)
{
int r;
struct sc_asn1_entry asn1_alg_id[3];
sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id);
sc_format_asn1_entry(asn1_alg_id + 0, &id->obj_id, NULL, 0);
r = asn1_decode(ctx, asn1_alg_id, in, len, NULL, NULL, 0, depth + 1);
if (r < 0)
return r;
return 0;
}
static int asn1_encode_algorithm_id(struct sc_context *ctx,
const struct sc_algorithm_id *id,
u8 **buf, size_t *len, int depth)
{
int r;
struct sc_asn1_entry asn1_alg_id[3];
sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id);
sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->obj_id, NULL, 1);
r = asn1_encode(ctx, asn1_alg_id, buf, len, depth + 1);
if (r < 0)
return r;
return 0;
}
static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_entry *entry,
const u8 *obj, size_t objlen, int depth)
{
@ -887,6 +927,10 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_entry *entry
if (entry->parm != NULL)
r = asn1_decode_p15_object(ctx, obj, objlen, (struct sc_asn1_pkcs15_object *) parm, depth);
break;
case SC_ASN1_ALGORITHM_ID:
if (entry->parm != NULL)
r = asn1_decode_algorithm_id(ctx, obj, objlen, (struct sc_algorithm_id *) parm, depth);
break;
case SC_ASN1_CALLBACK:
if (entry->parm != NULL)
r = callback_func(ctx, entry->arg, obj, objlen, depth);
@ -1067,6 +1111,9 @@ static int asn1_encode_entry(struct sc_context *ctx, const struct sc_asn1_entry
case SC_ASN1_PKCS15_OBJECT:
r = asn1_encode_p15_object(ctx, (const struct sc_asn1_pkcs15_object *) parm, &buf, &buflen, depth);
break;
case SC_ASN1_ALGORITHM_ID:
r = asn1_encode_algorithm_id(ctx, (const struct sc_algorithm_id *) parm, &buf, &buflen, depth);
break;
case SC_ASN1_CALLBACK:
r = callback_func(ctx, entry->arg, &buf, &buflen, depth);
break;

View File

@ -118,6 +118,7 @@ int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
#define SC_ASN1_PATH 256
#define SC_ASN1_PKCS15_ID 257
#define SC_ASN1_PKCS15_OBJECT 258
#define SC_ASN1_ALGORITHM_ID 259
/* use callback function */
#define SC_ASN1_CALLBACK 384

View File

@ -1094,7 +1094,7 @@ gpk_set_security_env(struct sc_card *card,
* what the hell, we have all those nice macros,
* so why not use them :)
*/
if (env->algorithm_flags & SC_PKCS15_HASH_SHA1) {
if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) {
context = GPK_AUTH_RSA_SHA;
priv->sec_hash_len = 20;
} else {

View File

@ -150,7 +150,7 @@ static int miocos_set_security_env(struct sc_card *card,
return SC_ERROR_NOT_SUPPORTED;
}
tmp.algorithm_ref = 0x00;
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_PKCS1_PAD)
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
tmp.algorithm_ref = 0x02;
#if 0
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)

View File

@ -20,17 +20,27 @@
#include "sc-internal.h"
#include "sc-log.h"
#include <string.h>
static const char *setcos_atrs[] = {
#define SETEC_PKI 1
#define SETEC_OTHER 2
static struct sc_atr_table setcos_atrs[] = {
/* the current FINEID card has this ATR: */
"3B:9F:94:40:1E:00:67:11:43:46:49:53:45:10:52:66:FF:81:90:00",
/* this is from a Nokia branded SC */
"3B:1F:11:00:67:80:42:46:49:53:45:10:52:66:FF:81:90:00",
{ "\x3B\x9F\x94\x40\x1E\x00\x67\x11\x43\x46\x49\x53\x45\x10\x52\x66\xFF\x81\x90\x00", 20, SETEC_PKI },
/* RSA SecurID 3100 */
"3B:9F:94:40:1E:00:67:16:43:46:49:53:45:10:52:66:FF:81:90:00",
NULL
{ "\x3B\x9F\x94\x40\x1E\x00\x67\x16\x43\x46\x49\x53\x45\x10\x52\x66\xFF\x81\x90\x00", 20, SETEC_PKI },
/* this is from a Nokia branded SC */
{ "\x3B\1F\x11\x00\x67\x80\x42\x46\x49\x53\x45\x10\x52\x66\xFF\x81\x90\x00", 18, SETEC_OTHER },
{ NULL }
};
struct setcos_priv_data {
int type;
};
#define DRVDATA(card) ((struct setcos_priv_data *) ((card)->drv_data))
static struct sc_card_operations setcos_ops;
static const struct sc_card_driver setcos_drv = {
"Setec smartcards",
@ -45,32 +55,36 @@ static int setcos_finish(struct sc_card *card)
static int setcos_match_card(struct sc_card *card)
{
int i, match = -1;
int i;
for (i = 0; setcos_atrs[i] != NULL; i++) {
u8 defatr[SC_MAX_ATR_SIZE];
size_t len = sizeof(defatr);
const char *atrp = setcos_atrs[i];
if (sc_hex_to_bin(atrp, defatr, &len))
continue;
if (len != card->atr_len)
continue;
if (memcmp(card->atr, defatr, len) != 0)
continue;
match = i;
break;
}
if (match == -1)
i = _sc_match_atr(card, setcos_atrs, NULL);
if (i < 0)
return 0;
return 1;
}
static int setcos_init(struct sc_card *card)
{
card->drv_data = NULL;
int i, id;
struct setcos_priv_data *priv = NULL;
i = _sc_match_atr(card, setcos_atrs, &id);
if (i < 0)
return 0;
priv = malloc(sizeof(struct setcos_priv_data));
if (priv == NULL)
return SC_ERROR_OUT_OF_MEMORY;
card->drv_data = priv;
card->cla = 0x00;
priv->type = id;
if (id == SETEC_PKI) {
unsigned long flags;
flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1;
flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1;
_sc_card_add_rsa_alg(card, 1024, flags, -1);
}
return 0;
}
@ -143,25 +157,31 @@ static int setcos_set_security_env(struct sc_card *card,
const struct sc_security_env *env,
int se_num)
{
struct setcos_priv_data *priv = DRVDATA(card);
if (env->flags & SC_SEC_ENV_ALG_PRESENT) {
struct sc_security_env tmp;
tmp = *env;
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
if (tmp.algorithm != SC_ALGORITHM_RSA) {
error(card->ctx, "Only RSA algorithm supported.\n");
return SC_ERROR_NOT_SUPPORTED;
}
tmp.algorithm_ref = 0x00;
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_PKCS1_PAD)
if (priv->type != SETEC_PKI) {
error(card->ctx, "Card does not support RSA.\n");
return SC_ERROR_NOT_SUPPORTED;
}
tmp.algorithm_ref = 0x00;
/* potential FIXME: return an error, if an unsupported
* pad or hash was requested, although this shouldn't happen.
*/
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
tmp.algorithm_ref = 0x02;
#if 0
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
tmp.algorithm_ref |= 0x10;
#endif
return iso_ops->set_security_env(card, &tmp, se_num);
tmp.algorithm_ref |= 0x10;
return iso_ops->set_security_env(card, &tmp, se_num);
}
return iso_ops->set_security_env(card, env, se_num);
}

View File

@ -97,7 +97,7 @@ static int tcos_set_security_env(struct sc_card *card,
return SC_ERROR_NOT_SUPPORTED;
}
tmp.algorithm_ref = 0x00;
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_PKCS1_PAD)
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
tmp.algorithm_ref = 0x02;
#if 0
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)

View File

@ -279,6 +279,7 @@ static struct sc_card * sc_card_new()
return NULL;
}
card->app_count = -1;
card->magic = SC_CARD_MAGIC;
pthread_mutex_init(&card->mutex, NULL);
return card;
@ -297,7 +298,10 @@ static void sc_card_free(struct sc_card *card)
free(card->app[i]);
}
free(card->ops);
if (card->algorithms != NULL)
free(card->algorithms);
pthread_mutex_destroy(&card->mutex);
card->magic = 0;
free(card);
}
@ -374,7 +378,6 @@ int sc_connect_card(struct sc_reader *reader, int slot_id,
r = SC_ERROR_INVALID_CARD;
goto err;
}
card->magic = SC_CARD_MAGIC;
*card_out = card;
SC_FUNC_RETURN(ctx, 1, 0);
@ -722,3 +725,68 @@ sc_card_ctl(struct sc_card *card, unsigned long cmd, void *args)
r = card->ops->card_ctl(card, cmd, args);
SC_FUNC_RETURN(card->ctx, 2, r);
}
int _sc_card_add_algorithm(struct sc_card *card, const struct sc_algorithm_info *info)
{
struct sc_algorithm_info *p;
assert(sc_card_valid(card) && info != NULL);
card->algorithms = realloc(card->algorithms, (card->algorithm_count + 1) * sizeof(*info));
if (card->algorithms == NULL) {
card->algorithm_count = 0;
return SC_ERROR_OUT_OF_MEMORY;
}
p = card->algorithms + card->algorithm_count;
card->algorithm_count++;
*p = *info;
return 0;
}
int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length,
unsigned long flags, long exponent)
{
struct sc_algorithm_info info;
memset(&info, 0, sizeof(info));
info.algorithm = SC_ALGORITHM_RSA;
info.key_length = key_length;
info.flags = flags;
info.u._rsa.exponent = exponent;
return _sc_card_add_algorithm(card, &info);
}
struct sc_algorithm_info * _sc_card_find_rsa_alg(struct sc_card *card,
unsigned int key_length)
{
int i;
for (i = 0; i < card->algorithm_count; i++) {
struct sc_algorithm_info *info = &card->algorithms[i];
if (info->algorithm != SC_ALGORITHM_RSA)
continue;
if (info->key_length != key_length)
continue;
return info;
}
return NULL;
}
int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *id_out)
{
const u8 *atr = card->atr;
size_t atr_len = card->atr_len;
int i = 0;
for (i = 0; table[i].atr != NULL; i++) {
if (table[i].atr_len != atr_len)
continue;
if (memcmp(table[i].atr, atr, atr_len) != 0)
continue;
if (id_out != NULL)
*id_out = table[i].id;
return i;
}
return -1;
}

View File

@ -33,12 +33,24 @@
struct sc_atr_table {
const u8 *atr;
size_t atr_len;
int id;
};
/* Internal use only */
int sc_check_sw(struct sc_card *card, int sw1, int sw2);
size_t _sc_count_bit_string_size(const void * buf, size_t bufsize);
int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader);
struct sc_slot_info * _sc_get_slot_info(struct sc_reader *reader, int slot_id);
/* Returns an index number if a match was found, -1 otherwise. table has to
* be null terminated. */
int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *id_out);
int _sc_card_add_algorithm(struct sc_card *card, const struct sc_algorithm_info *info);
int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length,
unsigned long flags, long exponent);
struct sc_algorithm_info * _sc_card_find_rsa_alg(struct sc_card *card,
unsigned int key_length);
#endif

View File

@ -246,16 +246,13 @@ struct sc_pkcs15_card * sc_pkcs15_card_new();
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card);
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey,
const struct sc_pkcs15_object *prkey_obj,
const u8 *in, size_t inlen, u8 *out, size_t outlen);
#define SC_PKCS15_HASH_SHA1 0x0001
#define SC_PKCS15_PAD_PKCS1_V1_5 0x10000
int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey,
unsigned int flags, const u8 *in, size_t inlen,
u8 *out, size_t outlen);
const struct sc_pkcs15_object *prkey_obj,
unsigned long alg_flags, const u8 *in,
size_t inlen, u8 *out, size_t outlen);
void sc_pkcs15_print_card(const struct sc_pkcs15_card *card);

View File

@ -232,12 +232,18 @@ struct sc_file {
#define SC_ALGORITHM_ONBOARD_KEY_GEN 0x80000000
#define SC_ALGORITHM_SPECIFIC_FLAGS 0x0000FFFF
#define SC_ALGORITHM_RSA_PKCS1_PAD 0x00000001
#define SC_ALGORITHM_RSA_PAD_2 0x00000002 /* forgot the names of */
#define SC_ALGORITHM_RSA_PAD_3 0x00000004 /* these two */
#define SC_ALGORITHM_RSA_RAW 0x00000001
#define SC_ALGORITHM_RSA_PAD_PKCS1 0x00000002
#define SC_ALGORITHM_RSA_PAD_ANSI 0x00000004
#define SC_ALGORITHM_RSA_PAD_ISO9796 0x00000008
#define SC_ALGORITHM_RSA_HASH_NONE 0x00000010
#define SC_ALGORITHM_RSA_HASH_SHA1 0x00000020
#define SC_ALGORITHM_RSA_HASH_MD5 0x00000040
#define SC_ALGORITHM_RSA_HASH_MD5_SHA1 0x00000080
struct sc_security_env {
int flags;
unsigned long flags;
int operation;
unsigned int algorithm, algorithm_flags;
@ -247,11 +253,16 @@ struct sc_security_env {
size_t key_ref_len;
};
struct sc_algorithm_id {
unsigned int algorithm;
struct sc_object_id obj_id;
};
struct sc_algorithm_info {
unsigned int algorithm;
unsigned int key_length;
unsigned int flags;
unsigned long flags;
union {
struct sc_rsa_info {
long exponent;
@ -380,6 +391,9 @@ struct sc_card {
int app_count;
struct sc_file *ef_dir;
struct sc_algorithm_info *algorithms;
int algorithm_count;
pthread_mutex_t mutex;
int lock_count;

View File

@ -28,13 +28,14 @@
#include <unistd.h>
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey,
const struct sc_pkcs15_object *obj,
const u8 * in, size_t inlen, u8 *out, size_t outlen)
{
int r;
struct sc_security_env senv;
struct sc_context *ctx = p15card->card->ctx;
struct sc_path path, file_id;
const struct sc_pkcs15_prkey_info *prkey = obj->data;
if (prkey->path.len < 2)
return SC_ERROR_INVALID_ARGUMENTS;
@ -48,7 +49,7 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
file_id.len = 2;
}
senv.algorithm = SC_ALGORITHM_RSA;
senv.algorithm_flags = SC_ALGORITHM_RSA_PKCS1_PAD;
senv.algorithm_flags = 0;
senv.file_ref = file_id;
senv.operation = SC_SEC_OPERATION_DECIPHER;
@ -90,16 +91,75 @@ static int pkcs1_add_padding(const u8 *in, size_t inlen, u8 *out, size_t outlen)
return 0;
}
static int add_padding(struct sc_context *ctx, const u8 *in, size_t inlen, u8 *out,
size_t *outlen, unsigned long flags, unsigned int mod_length)
{
u8 buf[64];
size_t buflen;
const u8 *hdr_md5 = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7"
"\x0d\x02\x05\x05\x05\x00\x04\x10";
size_t hdr_md5_len = 19;
const u8 *hdr_sha1 = "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a"
"\x05\x00\x04\x10";
size_t hdr_sha1_len = 15;
if (flags & SC_ALGORITHM_RSA_HASH_SHA1) {
if (inlen != 20)
return SC_ERROR_WRONG_LENGTH;
memcpy(buf, hdr_sha1, hdr_sha1_len);
memcpy(buf + hdr_sha1_len, in, 20);
buflen = 20 + hdr_sha1_len;
} else if (flags & SC_ALGORITHM_RSA_HASH_MD5) {
if (inlen != 16)
return SC_ERROR_WRONG_LENGTH;
memcpy(buf, hdr_md5, hdr_md5_len);
memcpy(buf + hdr_md5_len, in, 16);
buflen = 16 + hdr_md5_len;
} else if (flags & SC_ALGORITHM_RSA_HASH_MD5_SHA1) {
if (inlen != 36)
return SC_ERROR_WRONG_LENGTH;
memcpy(buf, in, 36);
buflen = 36;
} else
buflen = 0;
if (buflen) {
in = buf;
inlen = buflen;
}
if (flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
int r;
if (*outlen < mod_length)
return SC_ERROR_BUFFER_TOO_SMALL;
r = pkcs1_add_padding(in, inlen, out, mod_length);
if (r)
return r;
*outlen = mod_length;
} else {
if (*outlen < inlen)
return SC_ERROR_BUFFER_TOO_SMALL;
memcpy(out, in, inlen);
*outlen = inlen;
}
if (buflen)
memset(buf, 0, buflen);
return 0;
}
int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey,
unsigned int flags, const u8 *in, size_t inlen,
const struct sc_pkcs15_object *obj,
unsigned long flags, const u8 *in, size_t inlen,
u8 *out, size_t outlen)
{
int r;
struct sc_security_env senv;
struct sc_context *ctx = p15card->card->ctx;
u8 buf[256];
struct sc_algorithm_info *alg_info;
const struct sc_pkcs15_prkey_info *prkey = obj->data;
u8 buf[512];
size_t buflen;
struct sc_path path, file_id;
unsigned long pad_flags = 0;
if (prkey->path.len < 2)
return SC_ERROR_INVALID_ARGUMENTS;
@ -113,35 +173,74 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
memcpy(file_id.value, prkey->path.value + prkey->path.len - 2, 2);
file_id.len = 2;
}
senv.algorithm = SC_ALGORITHM_RSA;
senv.algorithm_flags = SC_ALGORITHM_RSA_PKCS1_PAD;
#if 0
if (flags & SC_PKCS15_HASH_SHA1)
senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
#endif
if (flags & SC_PKCS15_PAD_PKCS1_V1_5) {
size_t modlen = prkey->modulus_length >> 3;
if (inlen > (modlen - 11)) {
error(ctx, "Input data length too large.\n");
return SC_ERROR_INVALID_ARGUMENTS;
}
if (modlen > sizeof(buf)) {
error(ctx, "Too large modulus.\n");
return SC_ERROR_INTERNAL;
}
r = pkcs1_add_padding(in, inlen, buf, modlen);
SC_TEST_RET(p15card->card->ctx, r, "Error adding PKCS #1 padding");
in = buf;
inlen = modlen;
alg_info = _sc_card_find_rsa_alg(p15card->card, prkey->modulus_length);
if (alg_info == NULL) {
error(ctx, "Card does not support RSA with key length %d\n", prkey->modulus_length);
return SC_ERROR_NOT_SUPPORTED;
}
senv.file_ref = file_id;
senv.algorithm = SC_ALGORITHM_RSA;
memcpy(buf, in, inlen);
senv.algorithm_flags = 0;
if (flags & SC_ALGORITHM_RSA_HASH_SHA1) {
if (inlen != 20)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_WRONG_LENGTH);
if (!(alg_info->flags & SC_ALGORITHM_RSA_HASH_SHA1))
pad_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
else
senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
} else if (flags & SC_ALGORITHM_RSA_HASH_MD5) {
if (inlen != 16)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_WRONG_LENGTH);
if (!(alg_info->flags & SC_ALGORITHM_RSA_HASH_MD5))
pad_flags |= SC_ALGORITHM_RSA_HASH_MD5;
else
senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_MD5;
} else if (flags & SC_ALGORITHM_RSA_HASH_MD5_SHA1) {
if (inlen != 36)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_WRONG_LENGTH);
if (!(alg_info->flags & SC_ALGORITHM_RSA_HASH_MD5_SHA1))
pad_flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1;
else
senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1;
} else {
if (!(alg_info->flags & SC_ALGORITHM_RSA_HASH_NONE)) {
error(ctx, "Raw RSA not supported\n");
return SC_ERROR_NOT_SUPPORTED;
}
senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_NONE;
}
if (flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
if (!(alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1))
pad_flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
else
senv.algorithm_flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
} else if ((flags & SC_ALGORITHM_RSA_PAD_ANSI) ||
(flags & SC_ALGORITHM_RSA_PAD_ISO9796)) {
error(ctx, "Only PKCS #1 padding method supported\n");
return SC_ERROR_NOT_SUPPORTED;
} else {
if (!(alg_info->flags & SC_ALGORITHM_RSA_RAW)) {
error(ctx, "Card requires RSA padding\n");
return SC_ERROR_NOT_SUPPORTED;
}
senv.algorithm_flags |= SC_ALGORITHM_RSA_RAW;
}
if (pad_flags) {
buflen = sizeof(buf);
r = add_padding(ctx, in, inlen, buf, &buflen, pad_flags,
prkey->modulus_length/8);
SC_TEST_RET(ctx, r, "Unable to add padding");
in = buf;
inlen = buflen;
}
senv.file_ref = file_id;
senv.operation = SC_SEC_OPERATION_SIGN;
senv.key_ref_len = 1;
senv.key_ref[0] = prkey->key_reference & 0xFF;
senv.flags = SC_SEC_ENV_KEY_REF_PRESENT | SC_SEC_ENV_FILE_REF_PRESENT;
senv.flags |= SC_SEC_ENV_ALG_PRESENT;
SC_FUNC_CALLED(ctx, 1);
r = sc_select_file(p15card->card, &path, NULL);
SC_TEST_RET(ctx, r, "sc_select_file() failed");
#if 0
@ -152,6 +251,8 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
r = sc_set_security_env(p15card->card, &senv, 0);
SC_TEST_RET(ctx, r, "sc_set_security_env() failed");
r = sc_compute_signature(p15card->card, in, inlen, out, outlen);
if (pad_flags)
memset(buf, 0, inlen);
SC_TEST_RET(ctx, r, "sc_compute_signature() failed");
return r;

View File

@ -246,16 +246,13 @@ struct sc_pkcs15_card * sc_pkcs15_card_new();
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card);
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey,
const struct sc_pkcs15_object *prkey_obj,
const u8 *in, size_t inlen, u8 *out, size_t outlen);
#define SC_PKCS15_HASH_SHA1 0x0001
#define SC_PKCS15_PAD_PKCS1_V1_5 0x10000
int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey,
unsigned int flags, const u8 *in, size_t inlen,
u8 *out, size_t outlen);
const struct sc_pkcs15_object *prkey_obj,
unsigned long alg_flags, const u8 *in,
size_t inlen, u8 *out, size_t outlen);
void sc_pkcs15_print_card(const struct sc_pkcs15_card *card);

View File

@ -118,6 +118,7 @@ int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
#define SC_ASN1_PATH 256
#define SC_ASN1_PKCS15_ID 257
#define SC_ASN1_PKCS15_OBJECT 258
#define SC_ASN1_ALGORITHM_ID 259
/* use callback function */
#define SC_ASN1_CALLBACK 384

View File

@ -33,12 +33,24 @@
struct sc_atr_table {
const u8 *atr;
size_t atr_len;
int id;
};
/* Internal use only */
int sc_check_sw(struct sc_card *card, int sw1, int sw2);
size_t _sc_count_bit_string_size(const void * buf, size_t bufsize);
int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader);
struct sc_slot_info * _sc_get_slot_info(struct sc_reader *reader, int slot_id);
/* Returns an index number if a match was found, -1 otherwise. table has to
* be null terminated. */
int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *id_out);
int _sc_card_add_algorithm(struct sc_card *card, const struct sc_algorithm_info *info);
int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length,
unsigned long flags, long exponent);
struct sc_algorithm_info * _sc_card_find_rsa_alg(struct sc_card *card,
unsigned int key_length);
#endif

View File

@ -59,6 +59,7 @@ do { \
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/obj_mac.h>
#include <openssl/err.h>
#include <opensc.h>
#include <opensc-pkcs15.h>
@ -214,14 +215,15 @@ static int get_password(pam_handle_t * pamh, char **password, const char *pinnam
#endif
int verify_authenticity(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_prkey_info *prkey,
struct sc_pkcs15_object *prkey,
RSA *rsa)
{
int r;
u8 random_data[20];
u8 chg[256];
u8 chg[256], txt[256];
int chglen = sizeof(chg);
unsigned long flags;
DBG(printf("Getting random data...\n"));
r = get_random(random_data, sizeof(random_data));
@ -232,27 +234,27 @@ int verify_authenticity(struct sc_pkcs15_card *p15card,
DBG(printf("Too large RSA key. Bailing out.\n"));
return -1;
}
r = sc_pkcs15_compute_signature(p15card, prkey, SC_PKCS15_PAD_PKCS1_V1_5,
random_data, 20, chg, chglen);
flags = SC_ALGORITHM_RSA_PAD_PKCS1;
r = sc_pkcs15_compute_signature(p15card, prkey, flags, random_data, 20,
chg, chglen);
if (r < 0) {
DBG(printf("Compute signature failed: %s\n", sc_strerror(r)));
return -1;
}
DBG(printf("Verifying signature...\n"));
r = RSA_verify(NID_sha1, random_data, 20, chg, r, rsa);
if (r != 1) {
r = RSA_public_decrypt(chglen, chg, txt, rsa, RSA_PKCS1_PADDING);
if (r < 0) {
DBG(printf("No luck this time.\n"));
return 0;
} else
DBG(ERR_load_ERR_strings());
DBG(ERR_load_crypto_strings());
DBG(ERR_print_errors_fp(stdout));
DBG(ERR_free_strings());
return -1;
}
if (r == sizeof(random_data) && memcmp(txt, random_data, r) == 0)
return 1;
return 0;
}
u8 random_data[20];
u8 chg[256];
int chglen = sizeof(chg);
u8 plain_text[128];
#ifdef TEST
int main(int argc, const char **argv)
@ -266,15 +268,15 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, con
X509 *cert = NULL;
EVP_PKEY *pubkey = NULL;
struct sc_pkcs15_cert_info *cinfo;
struct sc_pkcs15_object *prkey, *pin;
struct sc_pkcs15_prkey_info *prkinfo = NULL;
struct sc_pkcs15_pin_info *pinfo = NULL;
struct sc_pkcs15_object *objs[32];
for (i = 0; i < argc; i++)
printf("%s\n", argv[i]);
#ifdef TEST
user = "jey";
user = getenv("USER");
#else
r = pam_get_user(pamh, &user, NULL);
if (r != PAM_SUCCESS)
@ -301,7 +303,6 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, con
}
ctx->error_file = stderr;
ctx->debug_file = stdout;
ctx->debug = 0;
for (i = 0; i < ctx->reader_count; i++) {
if (sc_detect_card_presence(ctx->reader[i], 0) == 1) {
DBG(printf("Connecting to %s...\n", ctx->reader[i]->name));
@ -326,37 +327,36 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, con
goto end;
}
DBG(printf("Enumerating certificates...\n"));
r = sc_pkcs15_enum_certificates(p15card);
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, objs, 32);
if (r < 0) {
printf("Cert enum failed: %s\n", sc_strerror(r));
goto end;
}
if (r == 0) /* No certificates found */
goto end;
for (i = 0; i < p15card->cert_count; i++) {
}
cinfo = &p15card->cert_info[0]; /* FIXME */
cinfo = objs[0]->data; /* FIXME */
DBG(printf("Finding private key...\n"));
r = sc_pkcs15_find_prkey_by_id(p15card, &cinfo->id, &prkinfo);
r = sc_pkcs15_find_prkey_by_id(p15card, &cinfo->id, &prkey);
if (r < 0)
goto end;
prkinfo = prkey->data;
DBG(printf("Finding PIN code...\n"));
r = sc_pkcs15_find_pin_by_auth_id(p15card, &prkinfo->com_attr.auth_id, &pinfo);
r = sc_pkcs15_find_pin_by_auth_id(p15card, &prkey->auth_id, &pin);
if (r < 0)
goto end;
DBG(printf("Asking for PIN code '%s'...\n", pinfo->com_attr.label));
DBG(printf("Asking for PIN code '%s'...\n", pin->label));
#ifdef TEST
password = strdup(getpass("Enter PIN1: "));
r = 0;
#else
r = get_password(pamh, &password, pinfo->com_attr.label);
r = get_password(pamh, &password, pin->label);
#endif
if (r) {
err = r;
goto end;
}
DBG(printf("Verifying PIN code...\n"));
r = sc_pkcs15_verify_pin(p15card, pinfo, (const u8 *) password, strlen(password));
r = sc_pkcs15_verify_pin(p15card, pin->data, (const u8 *) password, strlen(password));
memset(password, 0, strlen(password));
if (r) {
DBG(printf("PIN code verification failed: %s\n", sc_strerror(r)));
@ -365,16 +365,8 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, con
goto end;
}
DBG(printf("Awright! PIN code correct!\n"));
/* FIXME: clear password? */
DBG(printf("Deciphering...\n"));
#if 0
r = sc_pkcs15_decipher(p15card, prkinfo, chg, sizeof(chg), plain_text, sizeof(plain_text));
if (r <= 0) {
DBG(printf("Decipher failed: %s\n", sc_strerror(r)));
goto end;
}
#endif
if (verify_authenticity(p15card, prkinfo, pubkey->pkey.rsa) != 1)
DBG(printf("Generating signature...\n"));
if (verify_authenticity(p15card, prkey, pubkey->pkey.rsa) != 1)
goto end;
DBG(printf("You're in!\n"));
err = PAM_SUCCESS;

View File

@ -507,19 +507,21 @@ CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
debug(context, "Initiating signing operation.\n");
flags = SC_ALGORITHM_RSA_PAD_PKCS1;
switch (pMechanism->mechanism) {
case CKM_RSA_PKCS:
flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1; /* FIXME?? */
break;
case CKM_SHA1_RSA_PKCS:
flags = SC_PKCS15_HASH_SHA1;
flags |= SC_ALGORITHM_RSA_HASH_SHA1;
break;
default:
return CKR_MECHANISM_INVALID;
}
debug(context, "Selected flags %X. Now computing signature. %d bytes reserved.\n", flags, *pulDataLen);
debug(context, "Selected flags %X. Now computing signature for %d bytes. %d bytes reserved.\n", flags, ulDataLen, *pulDataLen);
rv = sc_pkcs15_compute_signature((struct sc_pkcs15_card*) ses->slot->card->fw_data,
prkey->prkey_info,
prkey->prkey_object,
flags,
pData,
ulDataLen,

View File

@ -136,9 +136,10 @@ int write_output(const u8 *buf, int len)
return 0;
}
int sign(struct sc_pkcs15_prkey_info *key)
int sign(struct sc_pkcs15_object *obj)
{
u8 buf[1024], out[1024];
struct sc_pkcs15_prkey_info *key = obj->data;
int r, c, len;
if (opt_input == NULL) {
@ -153,7 +154,12 @@ int sign(struct sc_pkcs15_prkey_info *key)
if (c < 0)
return 2;
len = sizeof(out);
r = sc_pkcs15_compute_signature(p15card, key, opt_crypt_flags,
if (!(opt_crypt_flags & SC_ALGORITHM_RSA_PAD_PKCS1) && c != key->modulus_length) {
fprintf(stderr, "Input has to be exactly %d bytes, when using no padding.\n",
key->modulus_length/8);
return 2;
}
r = sc_pkcs15_compute_signature(p15card, obj, opt_crypt_flags,
buf, c, out, len);
if (r < 0) {
fprintf(stderr, "Compute signature failed: %s\n", sc_strerror(r));
@ -164,7 +170,7 @@ int sign(struct sc_pkcs15_prkey_info *key)
return 0;
}
int decipher(struct sc_pkcs15_prkey_info *key)
int decipher(struct sc_pkcs15_object *obj)
{
u8 buf[1024], out[1024];
int r, c, len;
@ -177,7 +183,7 @@ int decipher(struct sc_pkcs15_prkey_info *key)
if (c < 0)
return 2;
len = sizeof(out);
r = sc_pkcs15_decipher(p15card, key, buf, c, out, len);
r = sc_pkcs15_decipher(p15card, obj, buf, c, out, len);
if (r < 0) {
fprintf(stderr, "Decrypt failed: %s\n", sc_strerror(r));
return 1;
@ -226,10 +232,10 @@ int main(int argc, char * const argv[])
opt_output = optarg;
break;
case OPT_SHA1:
opt_crypt_flags |= SC_PKCS15_HASH_SHA1;
opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
break;
case OPT_PKCS1:
opt_crypt_flags |= SC_PKCS15_PAD_PKCS1_V1_5;
opt_crypt_flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
break;
case 'q':
quiet++;
@ -331,12 +337,12 @@ int main(int argc, char * const argv[])
if (!quiet)
fprintf(stderr, "PIN code correct.\n");
if (do_decipher) {
if ((err = decipher(key->data)))
if ((err = decipher(key)))
goto end;
action_count--;
}
if (do_sign) {
if ((err = sign(key->data)))
if ((err = sign(key)))
goto end;
action_count--;
}