- added cryptoflex RSA key generation (not yet functional)

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1158 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2003-05-22 20:53:15 +00:00
parent e6864b5897
commit 795915e146
3 changed files with 160 additions and 8 deletions

View File

@ -43,7 +43,7 @@ static struct {
{ "3B:85:40:20:68:01:01:05:01", /* 8k */
TYPE_CRYPTOFLEX },
{ "3B:95:94:40:FF:63:01:01:02:01", /* 16k */
TYPE_CRYPTOFLEX },
TYPE_CRYPTOFLEX|FLAG_KEYGEN },
{ "3B:95:18:40:FF:64:02:01:01:02", /* 32K v4 */
TYPE_CRYPTOFLEX|FLAG_KEYGEN },
{ "3B:95:18:40:FF:62:01:02:01:04", /* 32K e-gate */
@ -818,12 +818,53 @@ static int flex_get_default_key(struct sc_card *card,
return sc_hex_to_bin(key, data->key_data, &data->len);
}
/* Generate key on-card */
static int flex_generate_key(sc_card_t *card, struct sc_cardctl_cryptoflex_genkey_info *data)
{
struct sc_apdu apdu;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
int r, p2;
switch (data->key_bits) {
case 512: p2 = 0x40; break;
case 768: p2 = 0x60; break;
case 1024: p2 = 0x80; break;
case 2048: p2 = 0x00; break;
default:
error(card->ctx, "Illegal key length: %d\n", data->key_bits);
return SC_ERROR_INVALID_ARGUMENTS;
}
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x01, p2);
apdu.cla = 0xF0;
apdu.data = sbuf;
apdu.datalen = 4;
apdu.lc = 4;
/* Little endian representation of exponent */
sbuf[0] = data->exponent;
sbuf[1] = data->exponent >> 8;
sbuf[2] = data->exponent >> 16;
sbuf[3] = data->exponent >> 24;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
SC_TEST_RET(card->ctx, r, "Card returned error");
data->pubkey_len = apdu.resplen;
return 0;
}
static int flex_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
{
switch (cmd) {
case SC_CARDCTL_GET_DEFAULT_KEY:
return flex_get_default_key(card,
(struct sc_cardctl_default_key *) ptr);
case SC_CARDCTL_CRYPTOFLEX_GENERATE_KEY:
return flex_generate_key(card,
(struct sc_cardctl_cryptoflex_genkey_info *) ptr);
}
return SC_ERROR_NOT_SUPPORTED;

View File

@ -47,6 +47,7 @@ enum {
* Cryptoflex specific calls
*/
SC_CARDCTL_CRYPTOFLEX_BASE = _CTL_PREFIX('C', 'F', 'X'),
SC_CARDCTL_CRYPTOFLEX_GENERATE_KEY,
/*
* MioCOS specific calls
@ -151,6 +152,16 @@ struct sc_cardctl_etoken_genkey_info {
unsigned short fid;
};
/*
* Cryptoflex info
*/
struct sc_cardctl_cryptoflex_genkey_info {
unsigned int key_bits;
unsigned long exponent;
unsigned char * pubkey;
unsigned int pubkey_len;
};
#ifdef __cplusplus
}
#endif

View File

@ -24,9 +24,12 @@
#include <string.h>
#include <sys/types.h>
#include <opensc/opensc.h>
#include <opensc/cardctl.h>
#include "pkcs15-init.h"
#include "profile.h"
static void invert_buf(u8 *dest, const u8 *src, size_t c);
/*
* Erase the card via rm -rf
*/
@ -190,6 +193,105 @@ cflex_new_file(struct sc_profile *profile, struct sc_card *card,
return 0;
}
/*
* Get the EF-pubkey corresponding to the EF-prkey
*/
int
cflex_pubkey_file(struct sc_file **ret, struct sc_file *prkf, unsigned int size)
{
struct sc_file *pukf;
sc_file_dup(&pukf, prkf);
sc_file_clear_acl_entries(pukf, SC_AC_OP_READ);
sc_file_add_acl_entry(pukf, SC_AC_OP_READ, SC_AC_NONE, SC_AC_KEY_REF_NONE);
pukf->path.len -= 2;
sc_append_path_id(&pukf->path, (const u8 *) "\x10\x12", 2);
pukf->id = 0x1012;
pukf->size = size;
*ret = pukf;
return 0;
}
/*
* RSA key generation
*/
static int
cflex_generate_key(struct sc_profile *profile, struct sc_card *card,
unsigned int index, unsigned int keybits,
sc_pkcs15_pubkey_t *pubkey,
struct sc_pkcs15_prkey_info *info)
{
struct sc_cardctl_cryptoflex_genkey_info args;
struct sc_file *prkf = NULL, *pukf = NULL;
unsigned char raw_pubkey[256];
unsigned char pinbuf[8];
size_t pinlen;
int r, delete_pukf = 0;
if ((r = cflex_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, index, &prkf)) < 0)
goto failed;
switch (keybits) {
case 512: prkf->size = 166; break;
case 768: prkf->size = 246; break;
case 1024: prkf->size = 326; break;
case 2048: prkf->size = 646; break;
default:
profile->cbs->error("Unsupported key size %u\n", keybits);
return SC_ERROR_INVALID_ARGUMENTS;
}
if ((r = cflex_pubkey_file(&pukf, prkf, prkf->size + 3)) < 0)
goto failed;
/* Get the CHV1 PIN */
pinlen = sizeof(pinbuf);
memset(pinbuf, 0, sizeof(pinbuf));
if ((r = sc_pkcs15init_get_secret(profile, card, SC_AC_CHV, 1, pinbuf, &pinlen)) < 0)
goto failed;
if ((r = sc_pkcs15init_create_file(profile, card, prkf)) < 0
|| (r = sc_pkcs15init_create_file(profile, card, pukf)) < 0)
goto failed;
delete_pukf = 1;
/* Present the PIN */
if ((r = sc_select_file(card, &pukf->path, NULL))
|| (r = sc_verify(card, SC_AC_CHV, 1, pinbuf, sizeof(pinbuf), NULL)) < 0)
goto failed;
memset(&args, 0, sizeof(args));
args.exponent = 0x10001;
args.key_bits = keybits;
r = sc_card_ctl(card, SC_CARDCTL_CRYPTOFLEX_GENERATE_KEY, &args);
if (r < 0)
goto failed;
/* extract public key */
pubkey->algorithm = SC_ALGORITHM_RSA;
pubkey->u.rsa.modulus.len = keybits / 8;
pubkey->u.rsa.modulus.data = malloc(keybits / 8);
pubkey->u.rsa.exponent.len = 3;
pubkey->u.rsa.exponent.data = malloc(3);
memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3);
if ((r = sc_select_file(card, &pukf->path, NULL)) < 0
|| (r = sc_read_binary(card, 4, raw_pubkey, pubkey->u.rsa.modulus.len, 0)) < 0)
goto failed;
invert_buf(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len);
info->key_reference = 1;
info->path = prkf->path;
failed: if (delete_pukf)
sc_pkcs15init_rmdir(card, profile, pukf);
if (r < 0)
sc_pkcs15init_rmdir(card, profile, prkf);
sc_file_free(pukf);
sc_file_free(prkf);
return r;
}
static void invert_buf(u8 *dest, const u8 *src, size_t c)
{
int i;
@ -372,13 +474,10 @@ cflex_new_key(struct sc_profile *profile, struct sc_card *card,
goto err;
info->path = keyfile->path;
info->modulus_length = rsa->modulus.len << 3;
sc_file_dup(&tmpfile, keyfile);
sc_file_clear_acl_entries(tmpfile, SC_AC_OP_READ);
sc_file_add_acl_entry(tmpfile, SC_AC_OP_READ, SC_AC_NONE, SC_AC_KEY_REF_NONE);
tmpfile->path.len -= 2;
sc_append_path_id(&tmpfile->path, (const u8 *) "\x10\x12", 2);
tmpfile->id = 0x1012;
tmpfile->size = pubsize;
if ((r = cflex_pubkey_file(&tmpfile, keyfile, pubsize)) < 0)
goto err;
printf("Updating RSA public key...\n");
r = sc_pkcs15init_update_file(profile, card, tmpfile, pub, pubsize);
err:
@ -393,4 +492,5 @@ struct sc_pkcs15init_operations sc_pkcs15init_cflex_operations = {
cflex_new_pin,
cflex_new_key,
cflex_new_file,
cflex_generate_key,
};