- 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 */
|
{ "3B:85:40:20:68:01:01:05:01", /* 8k */
|
||||||
TYPE_CRYPTOFLEX },
|
TYPE_CRYPTOFLEX },
|
||||||
{ "3B:95:94:40:FF:63:01:01:02:01", /* 16k */
|
{ "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 */
|
{ "3B:95:18:40:FF:64:02:01:01:02", /* 32K v4 */
|
||||||
TYPE_CRYPTOFLEX|FLAG_KEYGEN },
|
TYPE_CRYPTOFLEX|FLAG_KEYGEN },
|
||||||
{ "3B:95:18:40:FF:62:01:02:01:04", /* 32K e-gate */
|
{ "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);
|
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)
|
static int flex_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
|
||||||
{
|
{
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SC_CARDCTL_GET_DEFAULT_KEY:
|
case SC_CARDCTL_GET_DEFAULT_KEY:
|
||||||
return flex_get_default_key(card,
|
return flex_get_default_key(card,
|
||||||
(struct sc_cardctl_default_key *) ptr);
|
(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;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
|
|
@ -47,6 +47,7 @@ enum {
|
||||||
* Cryptoflex specific calls
|
* Cryptoflex specific calls
|
||||||
*/
|
*/
|
||||||
SC_CARDCTL_CRYPTOFLEX_BASE = _CTL_PREFIX('C', 'F', 'X'),
|
SC_CARDCTL_CRYPTOFLEX_BASE = _CTL_PREFIX('C', 'F', 'X'),
|
||||||
|
SC_CARDCTL_CRYPTOFLEX_GENERATE_KEY,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MioCOS specific calls
|
* MioCOS specific calls
|
||||||
|
@ -151,6 +152,16 @@ struct sc_cardctl_etoken_genkey_info {
|
||||||
unsigned short fid;
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,9 +24,12 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <opensc/opensc.h>
|
#include <opensc/opensc.h>
|
||||||
|
#include <opensc/cardctl.h>
|
||||||
#include "pkcs15-init.h"
|
#include "pkcs15-init.h"
|
||||||
#include "profile.h"
|
#include "profile.h"
|
||||||
|
|
||||||
|
static void invert_buf(u8 *dest, const u8 *src, size_t c);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Erase the card via rm -rf
|
* Erase the card via rm -rf
|
||||||
*/
|
*/
|
||||||
|
@ -190,6 +193,105 @@ cflex_new_file(struct sc_profile *profile, struct sc_card *card,
|
||||||
return 0;
|
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)
|
static void invert_buf(u8 *dest, const u8 *src, size_t c)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -372,13 +474,10 @@ cflex_new_key(struct sc_profile *profile, struct sc_card *card,
|
||||||
goto err;
|
goto err;
|
||||||
info->path = keyfile->path;
|
info->path = keyfile->path;
|
||||||
info->modulus_length = rsa->modulus.len << 3;
|
info->modulus_length = rsa->modulus.len << 3;
|
||||||
sc_file_dup(&tmpfile, keyfile);
|
|
||||||
sc_file_clear_acl_entries(tmpfile, SC_AC_OP_READ);
|
if ((r = cflex_pubkey_file(&tmpfile, keyfile, pubsize)) < 0)
|
||||||
sc_file_add_acl_entry(tmpfile, SC_AC_OP_READ, SC_AC_NONE, SC_AC_KEY_REF_NONE);
|
goto err;
|
||||||
tmpfile->path.len -= 2;
|
|
||||||
sc_append_path_id(&tmpfile->path, (const u8 *) "\x10\x12", 2);
|
|
||||||
tmpfile->id = 0x1012;
|
|
||||||
tmpfile->size = pubsize;
|
|
||||||
printf("Updating RSA public key...\n");
|
printf("Updating RSA public key...\n");
|
||||||
r = sc_pkcs15init_update_file(profile, card, tmpfile, pub, pubsize);
|
r = sc_pkcs15init_update_file(profile, card, tmpfile, pub, pubsize);
|
||||||
err:
|
err:
|
||||||
|
@ -393,4 +492,5 @@ struct sc_pkcs15init_operations sc_pkcs15init_cflex_operations = {
|
||||||
cflex_new_pin,
|
cflex_new_pin,
|
||||||
cflex_new_key,
|
cflex_new_key,
|
||||||
cflex_new_file,
|
cflex_new_file,
|
||||||
|
cflex_generate_key,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue