- 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:
parent
e6864b5897
commit
795915e146
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue