implement key generation
This commit is contained in:
10
ChangeLog
10
ChangeLog
@@ -1,5 +1,15 @@
|
|||||||
2012-06-07 Niibe Yutaka <gniibe@fsij.org>
|
2012-06-07 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
Implement key generation.
|
||||||
|
* src/openpgp.c (cmd_pgp_gakp): Call gpg_do_keygen.
|
||||||
|
* src/openpgp-do.c (proc_key_import): Call with modulus = NULL.
|
||||||
|
(gpg_do_keygen): New function.
|
||||||
|
(gpg_reset_digital_signature_counter): New function.
|
||||||
|
(gpg_do_write_prvkey): New argument MODULUS. Call
|
||||||
|
gpg_reset_digital_signature_counter.
|
||||||
|
* src/call-rsa.c (rsa_genkey): New function.
|
||||||
|
* src/random.c (random_byte): New function.
|
||||||
|
|
||||||
PolarSSL modification.
|
PolarSSL modification.
|
||||||
* polarssl-0.14.0/library/rsa.c (rsa_gen_key): Don't set D, DP,
|
* polarssl-0.14.0/library/rsa.c (rsa_gen_key): Don't set D, DP,
|
||||||
DQ, and QP. It's only for key generation.
|
DQ, and QP. It's only for key generation.
|
||||||
|
|||||||
16
README
16
README
@@ -135,6 +135,7 @@ Tested features are:
|
|||||||
* Card holder certificate
|
* Card holder certificate
|
||||||
* Removal of keys (Overriding key import is not supported,
|
* Removal of keys (Overriding key import is not supported,
|
||||||
but you can remove all keys to import again).
|
but you can remove all keys to import again).
|
||||||
|
* Key generation on device side
|
||||||
|
|
||||||
It is known not-working well:
|
It is known not-working well:
|
||||||
|
|
||||||
@@ -142,10 +143,6 @@ It is known not-working well:
|
|||||||
work well. Please make sure to disable DEBUG option if it
|
work well. Please make sure to disable DEBUG option if it
|
||||||
doesn't work well.
|
doesn't work well.
|
||||||
|
|
||||||
Not supported feature(s):
|
|
||||||
|
|
||||||
* Key generation on device side
|
|
||||||
|
|
||||||
|
|
||||||
Targets
|
Targets
|
||||||
=======
|
=======
|
||||||
@@ -566,9 +563,12 @@ command is:
|
|||||||
Note that the factory setting of user password is "123456" and admin
|
Note that the factory setting of user password is "123456" and admin
|
||||||
password is "12345678" as the specification.
|
password is "12345678" as the specification.
|
||||||
|
|
||||||
No, Gnuk doesn't support key generation. You need to create your
|
It is recommended to create your keys on your computer, and import
|
||||||
keys on your computer, and import them to Gnuk Token. After you create
|
them to Gnuk Token. After you create your keys (they must be 2048-bit
|
||||||
your keys (they must be 2048-bit RSA), you can import them.
|
RSA), you can import them.
|
||||||
|
|
||||||
|
Gnuk supports key generation, but this feature is young and should be
|
||||||
|
considered experimental.
|
||||||
|
|
||||||
For detail, please see doc/DEMO and doc/DEMO-2.
|
For detail, please see doc/DEMO and doc/DEMO-2.
|
||||||
|
|
||||||
@@ -577,7 +577,7 @@ you can import the keys (again) to (possibly another) Gnuk Token. In
|
|||||||
this case, you can use GnuPG's option to specify the home directory by
|
this case, you can use GnuPG's option to specify the home directory by
|
||||||
--homedir.
|
--homedir.
|
||||||
|
|
||||||
After creating keys by:
|
After creating keys on your computer by:
|
||||||
|
|
||||||
$ gpg --gen-key
|
$ gpg --gen-key
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
*
|
*
|
||||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
@@ -211,3 +211,35 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RSA_EXPONENT 0x10001
|
||||||
|
|
||||||
|
const uint8_t *
|
||||||
|
rsa_genkey (void)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
uint8_t index = 0;
|
||||||
|
uint8_t *p_q_modulus = (uint8_t *)malloc (KEY_CONTENT_LEN*2);
|
||||||
|
uint8_t *p = p_q_modulus;
|
||||||
|
uint8_t *q = p_q_modulus + KEY_CONTENT_LEN/2;
|
||||||
|
uint8_t *modulus = p_q_modulus + KEY_CONTENT_LEN;
|
||||||
|
|
||||||
|
if (p_q_modulus == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||||
|
r = rsa_gen_key (&rsa_ctx, random_byte, &index,
|
||||||
|
KEY_CONTENT_LEN * 8, RSA_EXPONENT);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
free (p_q_modulus);
|
||||||
|
rsa_free (&rsa_ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpi_write_binary (&rsa_ctx.P, p, KEY_CONTENT_LEN/2);
|
||||||
|
mpi_write_binary (&rsa_ctx.Q, q, KEY_CONTENT_LEN/2);
|
||||||
|
mpi_write_binary (&rsa_ctx.N, modulus, KEY_CONTENT_LEN);
|
||||||
|
rsa_free (&rsa_ctx);
|
||||||
|
return p_q_modulus;
|
||||||
|
}
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ extern void gpg_data_copy (const uint8_t *p);
|
|||||||
extern void gpg_do_get_data (uint16_t tag, int with_tag);
|
extern void gpg_do_get_data (uint16_t tag, int with_tag);
|
||||||
extern void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len);
|
extern void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len);
|
||||||
extern void gpg_do_public_key (uint8_t kk_byte);
|
extern void gpg_do_public_key (uint8_t kk_byte);
|
||||||
|
extern void gpg_do_keygen (uint8_t kk_byte);
|
||||||
|
|
||||||
extern const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
|
extern const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
|
||||||
|
|
||||||
@@ -234,6 +235,7 @@ extern void modulus_free (const uint8_t *);
|
|||||||
extern int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *);
|
extern int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *);
|
||||||
extern int rsa_verify (const uint8_t *pubkey, const uint8_t *hash,
|
extern int rsa_verify (const uint8_t *pubkey, const uint8_t *hash,
|
||||||
const uint8_t *signature);
|
const uint8_t *signature);
|
||||||
|
extern const uint8_t *rsa_genkey (void);
|
||||||
|
|
||||||
extern const uint8_t *gpg_do_read_simple (uint8_t);
|
extern const uint8_t *gpg_do_read_simple (uint8_t);
|
||||||
extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
|
extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
|
||||||
@@ -327,6 +329,8 @@ extern const uint8_t *random_bytes_get (void);
|
|||||||
extern void random_bytes_free (const uint8_t *);
|
extern void random_bytes_free (const uint8_t *);
|
||||||
/* 4-byte salt */
|
/* 4-byte salt */
|
||||||
extern uint32_t get_salt (void);
|
extern uint32_t get_salt (void);
|
||||||
|
/* iterator returning a byta at a time */
|
||||||
|
extern uint8_t random_byte (void *arg);
|
||||||
|
|
||||||
extern uint32_t hardclock (void);
|
extern uint32_t hardclock (void);
|
||||||
|
|
||||||
|
|||||||
108
src/openpgp-do.c
108
src/openpgp-do.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
|
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
*
|
*
|
||||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
@@ -163,6 +163,17 @@ gpg_write_digital_signature_counter (const uint8_t *p, uint32_t dsc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gpg_reset_digital_signature_counter (void)
|
||||||
|
{
|
||||||
|
if (digital_signature_counter != 0)
|
||||||
|
{
|
||||||
|
flash_put_data (NR_COUNTER_DS);
|
||||||
|
flash_put_data (NR_COUNTER_DS_LSB);
|
||||||
|
digital_signature_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gpg_increment_digital_signature_counter (void)
|
gpg_increment_digital_signature_counter (void)
|
||||||
{
|
{
|
||||||
@@ -673,12 +684,11 @@ static int8_t num_prv_keys;
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||||
const uint8_t *keystring_admin)
|
const uint8_t *keystring_admin, const uint8_t *modulus)
|
||||||
{
|
{
|
||||||
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
||||||
const uint8_t *p;
|
const uint8_t *p;
|
||||||
int r;
|
int r;
|
||||||
const uint8_t *modulus;
|
|
||||||
struct prvkey_data *pd;
|
struct prvkey_data *pd;
|
||||||
uint8_t *key_addr;
|
uint8_t *key_addr;
|
||||||
const uint8_t *dek;
|
const uint8_t *dek;
|
||||||
@@ -686,10 +696,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
const uint8_t *ks_pw1;
|
const uint8_t *ks_pw1;
|
||||||
const uint8_t *ks_rc;
|
const uint8_t *ks_rc;
|
||||||
struct key_data_internal kdi;
|
struct key_data_internal kdi;
|
||||||
|
int modulus_allocated_here = 0;
|
||||||
#if 0
|
|
||||||
assert (key_len == KEY_CONTENT_LEN);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DEBUG_INFO ("Key import\r\n");
|
DEBUG_INFO ("Key import\r\n");
|
||||||
DEBUG_SHORT (key_len);
|
DEBUG_SHORT (key_len);
|
||||||
@@ -698,10 +705,15 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
/* No replace support, you need to remove it first. */
|
/* No replace support, you need to remove it first. */
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (key_len != KEY_CONTENT_LEN)
|
||||||
|
return -1;
|
||||||
|
|
||||||
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
|
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
|
||||||
if (pd == NULL)
|
if (pd == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (modulus == NULL)
|
||||||
|
{
|
||||||
modulus = modulus_calc (key_data, key_len);
|
modulus = modulus_calc (key_data, key_len);
|
||||||
if (modulus == NULL)
|
if (modulus == NULL)
|
||||||
{
|
{
|
||||||
@@ -709,11 +721,15 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modulus_allocated_here = 1;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG_INFO ("Getting keystore address...\r\n");
|
DEBUG_INFO ("Getting keystore address...\r\n");
|
||||||
key_addr = flash_key_alloc ();
|
key_addr = flash_key_alloc ();
|
||||||
if (key_addr == NULL)
|
if (key_addr == NULL)
|
||||||
{
|
{
|
||||||
free (pd);
|
free (pd);
|
||||||
|
if (modulus_allocated_here)
|
||||||
modulus_free (modulus);
|
modulus_free (modulus);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -736,6 +752,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
encrypt (dek, (uint8_t *)&kdi, sizeof (struct key_data_internal));
|
encrypt (dek, (uint8_t *)&kdi, sizeof (struct key_data_internal));
|
||||||
|
|
||||||
r = flash_key_write (key_addr, kdi.data, modulus);
|
r = flash_key_write (key_addr, kdi.data, modulus);
|
||||||
|
if (modulus_allocated_here)
|
||||||
modulus_free (modulus);
|
modulus_free (modulus);
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@@ -749,7 +766,10 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
memcpy (pd->crm_encrypted, (uint8_t *)&kdi.check, ADDITIONAL_DATA_SIZE);
|
memcpy (pd->crm_encrypted, (uint8_t *)&kdi.check, ADDITIONAL_DATA_SIZE);
|
||||||
|
|
||||||
if (kk == GPG_KEY_FOR_SIGNING)
|
if (kk == GPG_KEY_FOR_SIGNING)
|
||||||
|
{
|
||||||
ac_reset_pso_cds ();
|
ac_reset_pso_cds ();
|
||||||
|
gpg_reset_digital_signature_counter ();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ac_reset_other ();
|
ac_reset_other ();
|
||||||
|
|
||||||
@@ -908,7 +928,7 @@ proc_key_import (const uint8_t *data, int len)
|
|||||||
|
|
||||||
/* It should starts with 00 01 00 01 (E) */
|
/* It should starts with 00 01 00 01 (E) */
|
||||||
/* Skip E, 4-byte */
|
/* Skip E, 4-byte */
|
||||||
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin);
|
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
@@ -1460,3 +1480,75 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
|
|||||||
else
|
else
|
||||||
*do_data_p = NULL;
|
*do_data_p = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gpg_do_keygen (uint8_t kk_byte)
|
||||||
|
{
|
||||||
|
enum kind_of_key kk;
|
||||||
|
const uint8_t *keystring_admin;
|
||||||
|
const uint8_t *p_q_modulus;
|
||||||
|
const uint8_t *p_q;
|
||||||
|
const uint8_t *modulus;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
DEBUG_INFO ("Keygen\r\n");
|
||||||
|
DEBUG_BYTE (kk_byte);
|
||||||
|
|
||||||
|
if (kk_byte == 0xb6)
|
||||||
|
kk = GPG_KEY_FOR_SIGNING;
|
||||||
|
else if (kk_byte == 0xb8)
|
||||||
|
kk = GPG_KEY_FOR_DECRYPTION;
|
||||||
|
else /* 0xa4 */
|
||||||
|
kk = GPG_KEY_FOR_AUTHENTICATION;
|
||||||
|
|
||||||
|
if (admin_authorized == BY_ADMIN)
|
||||||
|
keystring_admin = keystring_md_pw3;
|
||||||
|
else
|
||||||
|
keystring_admin = NULL;
|
||||||
|
|
||||||
|
p_q_modulus = rsa_genkey ();
|
||||||
|
if (p_q_modulus == NULL)
|
||||||
|
{
|
||||||
|
GPG_MEMORY_FAILURE ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_q = p_q_modulus;
|
||||||
|
modulus = p_q_modulus + KEY_CONTENT_LEN;
|
||||||
|
|
||||||
|
r = gpg_do_write_prvkey (kk, p_q, KEY_CONTENT_LEN,
|
||||||
|
keystring_admin, modulus);
|
||||||
|
free ((uint8_t *)p_q_modulus);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
GPG_ERROR ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_INFO ("Calling gpg_do_public_key...\r\n");
|
||||||
|
|
||||||
|
if (kk == GPG_KEY_FOR_SIGNING)
|
||||||
|
{
|
||||||
|
/* Authintication has been reset within gpg_do_write_prvkey. */
|
||||||
|
/* But GnuPG expects it's ready for signing. */
|
||||||
|
/* Thus, we call verify_pso_cds here. */
|
||||||
|
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||||
|
const uint8_t *pw;
|
||||||
|
int pw_len;
|
||||||
|
|
||||||
|
if (ks_pw1)
|
||||||
|
{
|
||||||
|
pw = ks_pw1+1;
|
||||||
|
pw_len = ks_pw1[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
|
||||||
|
pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_pso_cds (pw, pw_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpg_do_public_key (kk_byte);
|
||||||
|
}
|
||||||
|
|||||||
@@ -480,12 +480,11 @@ cmd_pgp_gakp (void)
|
|||||||
/* Get public key */
|
/* Get public key */
|
||||||
gpg_do_public_key (apdu.cmd_apdu_data[0]);
|
gpg_do_public_key (apdu.cmd_apdu_data[0]);
|
||||||
else
|
else
|
||||||
{ /* Generate key pair */
|
{
|
||||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||||
GPG_SECURITY_FAILURE ();
|
GPG_SECURITY_FAILURE ();
|
||||||
|
/* Generate key pair */
|
||||||
/* XXX: Not yet supported */
|
gpg_do_keygen (apdu.cmd_apdu_data[0]);
|
||||||
GPG_ERROR ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
src/random.c
27
src/random.c
@@ -70,3 +70,30 @@ get_salt (void)
|
|||||||
{
|
{
|
||||||
return neug_get (NEUG_KICK_FILLING);
|
return neug_get (NEUG_KICK_FILLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rundom byte iterator
|
||||||
|
*/
|
||||||
|
uint8_t
|
||||||
|
random_byte (void *arg)
|
||||||
|
{
|
||||||
|
uint8_t *index_p = (uint8_t *)arg;
|
||||||
|
uint8_t index = *index_p;
|
||||||
|
uint8_t *p = ((uint8_t *)random_word) + index;
|
||||||
|
uint8_t v;
|
||||||
|
|
||||||
|
neug_wait_full ();
|
||||||
|
|
||||||
|
v = *p;
|
||||||
|
|
||||||
|
if (++index >= RANDOM_BYTES_LENGTH)
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
neug_flush ();
|
||||||
|
}
|
||||||
|
|
||||||
|
*index_p = index;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user