mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Note: I have not fully tested the new key creation due to a pc/sc
error. However the backupfile has been created successfully. * rsa.c (rsa_generate): Return the dummy list of factors only if the caller asked for it. * card_util.c (generate_card_keys): ask whether backup should be created. (card_store_subkey): Factored some code out to .. * keygen.c (save_unprotected_key_to_card): .. new function. (gen_card_key_with_backup): New. (generate_raw_key): New. (generate_keypair): New arg BACKUP_ENCRYPTION_DIR. Changed all callers. (do_generate_keypair): Divert to gen_card_key_with_backup when desired.
This commit is contained in:
parent
42c18de83a
commit
f36154535e
@ -1,3 +1,8 @@
|
||||
2004-09-23 Werner Koch <wk@g10code.com>
|
||||
|
||||
* rsa.c (rsa_generate): Return the dummy list of factors only if
|
||||
the caller asked for it.
|
||||
|
||||
2004-05-20 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* dsa.c (verify): s/exp/exponent/ to fix a compiler warning. From
|
||||
|
@ -353,7 +353,8 @@ rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
|
||||
skey[4] = sk.q;
|
||||
skey[5] = sk.u;
|
||||
/* make an empty list of factors */
|
||||
*retfactors = m_alloc_clear( 1 * sizeof **retfactors );
|
||||
if (retfactors)
|
||||
*retfactors = m_alloc_clear( 1 * sizeof **retfactors );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,16 @@
|
||||
2004-09-23 Werner Koch <wk@g10code.com>
|
||||
|
||||
* card_util.c (generate_card_keys): ask whether backup should be
|
||||
created.
|
||||
(card_store_subkey): Factored some code out to ..
|
||||
* keygen.c (save_unprotected_key_to_card): .. new function.
|
||||
(gen_card_key_with_backup): New.
|
||||
(generate_raw_key): New.
|
||||
(generate_keypair): New arg BACKUP_ENCRYPTION_DIR. Changed all
|
||||
callers.
|
||||
(do_generate_keypair): Divert to gen_card_key_with_backup when
|
||||
desired.
|
||||
|
||||
* apdu.c (open_pcsc_reader): Do not print empty reader string.
|
||||
|
||||
* keygen.c (ask_algo): Allow creation of AUTH keys.
|
||||
@ -7,6 +18,9 @@
|
||||
* keyid.c (usagestr_from_pk): New.
|
||||
|
||||
* app-openpgp.c (app_openpgp_storekey): Call flush_cache.
|
||||
(get_cached_data): Move local data initialization to ..
|
||||
(app_select_openpgp): .. here. Read some flags for later use.
|
||||
(do_getattr): New read-only attribute EXTCAP.
|
||||
|
||||
* keyedit.c (keyedit_menu): New command "keytocard"
|
||||
(keyedit_menu): Bad hack for the not_with_sk element.
|
||||
@ -15,6 +29,7 @@
|
||||
|
||||
* card-util.c (card_store_subkey): New.
|
||||
(copy_mpi): New.
|
||||
|
||||
* cardglue.c (agent_openpgp_storekey): New.
|
||||
|
||||
2004-09-22 Werner Koch <wk@g10code.com>
|
||||
|
@ -63,11 +63,11 @@ static struct {
|
||||
{ 0x006E, 1, 0, 1, 0, 0, "Application Related Data" },
|
||||
{ 0x004F, 0, 0x6E, 1, 0, 0, "AID" },
|
||||
{ 0x0073, 1, 0, 1, 0, 0, "Discretionary Data Objects" },
|
||||
{ 0x0047, 0, 0x6E, 1, 0, 0, "Card Capabilities" },
|
||||
{ 0x00C0, 0, 0x6E, 1, 0, 0, "Extended Card Capabilities" },
|
||||
{ 0x00C1, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Signature" },
|
||||
{ 0x00C2, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Decryption" },
|
||||
{ 0x00C3, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Authentication" },
|
||||
{ 0x0047, 0, 0x6E, 1, 1, 0, "Card Capabilities" },
|
||||
{ 0x00C0, 0, 0x6E, 1, 1, 0, "Extended Card Capabilities" },
|
||||
{ 0x00C1, 0, 0x6E, 1, 1, 0, "Algorithm Attributes Signature" },
|
||||
{ 0x00C2, 0, 0x6E, 1, 1, 0, "Algorithm Attributes Decryption" },
|
||||
{ 0x00C3, 0, 0x6E, 1, 1, 0, "Algorithm Attributes Authentication" },
|
||||
{ 0x00C4, 0, 0x6E, 1, 0, 1, "CHV Status Bytes" },
|
||||
{ 0x00C5, 0, 0x6E, 1, 0, 0, "Fingerprints" },
|
||||
{ 0x00C6, 0, 0x6E, 1, 0, 0, "CA Fingerprints" },
|
||||
@ -86,6 +86,13 @@ struct cache_s {
|
||||
|
||||
struct app_local_s {
|
||||
struct cache_s *cache;
|
||||
struct
|
||||
{
|
||||
unsigned int get_challenge:1;
|
||||
unsigned int key_import:1;
|
||||
unsigned int change_force_chv:1;
|
||||
unsigned int private_dos:1;
|
||||
} extcap;
|
||||
};
|
||||
|
||||
|
||||
@ -127,25 +134,23 @@ get_cached_data (app_t app, int tag,
|
||||
*result = NULL;
|
||||
*resultlen = 0;
|
||||
|
||||
if (app->app_local)
|
||||
{
|
||||
for (c=app->app_local->cache; c; c = c->next)
|
||||
if (c->tag == tag)
|
||||
for (c=app->app_local->cache; c; c = c->next)
|
||||
if (c->tag == tag)
|
||||
{
|
||||
if(c->length)
|
||||
{
|
||||
if(c->length)
|
||||
{
|
||||
p = xtrymalloc (c->length);
|
||||
if (!p)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
memcpy (p, c->data, c->length);
|
||||
*result = p;
|
||||
}
|
||||
|
||||
*resultlen = c->length;
|
||||
|
||||
return 0;
|
||||
p = xtrymalloc (c->length);
|
||||
if (!p)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
memcpy (p, c->data, c->length);
|
||||
*result = p;
|
||||
}
|
||||
}
|
||||
|
||||
*resultlen = c->length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
err = iso7816_get_data (app->slot, tag, &p, &len);
|
||||
if (err)
|
||||
@ -163,24 +168,18 @@ get_cached_data (app_t app, int tag,
|
||||
}
|
||||
|
||||
/* No, cache it. */
|
||||
if (!app->app_local)
|
||||
app->app_local = xtrycalloc (1, sizeof *app->app_local);
|
||||
|
||||
/* Note that we can safely ignore out of core errors. */
|
||||
if (app->app_local)
|
||||
for (c=app->app_local->cache; c; c = c->next)
|
||||
assert (c->tag != tag);
|
||||
|
||||
c = xtrymalloc (sizeof *c + len);
|
||||
if (c)
|
||||
{
|
||||
for (c=app->app_local->cache; c; c = c->next)
|
||||
assert (c->tag != tag);
|
||||
|
||||
c = xtrymalloc (sizeof *c + len);
|
||||
if (c)
|
||||
{
|
||||
memcpy (c->data, p, len);
|
||||
c->length = len;
|
||||
c->tag = tag;
|
||||
c->next = app->app_local->cache;
|
||||
app->app_local->cache = c;
|
||||
}
|
||||
memcpy (c->data, p, len);
|
||||
c->length = len;
|
||||
c->tag = tag;
|
||||
c->next = app->app_local->cache;
|
||||
app->app_local->cache = c;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -505,6 +504,7 @@ do_getattr (APP app, CTRL ctrl, const char *name)
|
||||
{ "SIG-COUNTER", 0x0093, 2 },
|
||||
{ "SERIALNO", 0x004F, -1 },
|
||||
{ "AID", 0x004F },
|
||||
{ "EXTCAP", 0x0000, -2 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
int idx, i;
|
||||
@ -539,6 +539,18 @@ do_getattr (APP app, CTRL ctrl, const char *name)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (table[idx].special == -2)
|
||||
{
|
||||
char tmp[50];
|
||||
|
||||
sprintf (tmp, "gc=%d ki=%d fc=%d pd=%d",
|
||||
app->app_local->extcap.get_challenge,
|
||||
app->app_local->extcap.key_import,
|
||||
app->app_local->extcap.change_force_chv,
|
||||
app->app_local->extcap.private_dos);
|
||||
send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
relptr = get_one_do (app, table[idx].tag, &value, &valuelen);
|
||||
if (relptr)
|
||||
@ -578,6 +590,7 @@ do_getattr (APP app, CTRL ctrl, const char *name)
|
||||
static int
|
||||
do_learn_status (APP app, CTRL ctrl)
|
||||
{
|
||||
do_getattr (app, ctrl, "EXTCAP");
|
||||
do_getattr (app, ctrl, "DISP-NAME");
|
||||
do_getattr (app, ctrl, "DISP-LANG");
|
||||
do_getattr (app, ctrl, "DISP-SEX");
|
||||
@ -1378,11 +1391,14 @@ app_select_openpgp (APP app)
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid);
|
||||
if (!rc)
|
||||
{
|
||||
unsigned int manufacturer;
|
||||
|
||||
app->apptype = "OPENPGP";
|
||||
|
||||
app->did_chv1 = 0;
|
||||
app->did_chv2 = 0;
|
||||
app->did_chv3 = 0;
|
||||
app->app_local = NULL;
|
||||
|
||||
/* The OpenPGP card returns the serial number as part of the
|
||||
AID; because we prefer to use OpenPGP serial numbers, we
|
||||
@ -1400,10 +1416,18 @@ app_select_openpgp (APP app)
|
||||
|
||||
app->card_version = buffer[6] << 8;
|
||||
app->card_version |= buffer[7];
|
||||
manufacturer = (buffer[8]<<8 | buffer[9]);
|
||||
|
||||
xfree (app->serialno);
|
||||
app->serialno = buffer;
|
||||
app->serialnolen = buflen;
|
||||
buffer = NULL;
|
||||
app->app_local = xtrycalloc (1, sizeof *app->app_local);
|
||||
if (!app->app_local)
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
relptr = get_one_do (app, 0x00C4, &buffer, &buflen);
|
||||
if (!relptr)
|
||||
@ -1413,7 +1437,29 @@ app_select_openpgp (APP app)
|
||||
}
|
||||
app->force_chv1 = (buflen && *buffer == 0);
|
||||
xfree (relptr);
|
||||
|
||||
|
||||
relptr = get_one_do (app, 0x00C0, &buffer, &buflen);
|
||||
if (!relptr)
|
||||
{
|
||||
log_error ("can't access Extended Capability Flags - "
|
||||
"invalid OpenPGP card?\n");
|
||||
goto leave;
|
||||
}
|
||||
if (buflen)
|
||||
{
|
||||
app->app_local->extcap.get_challenge = !!(*buffer & 0x40);
|
||||
app->app_local->extcap.key_import = !!(*buffer & 0x20);
|
||||
app->app_local->extcap.change_force_chv = !!(*buffer & 0x10);
|
||||
app->app_local->extcap.private_dos = !!(*buffer & 0x08);
|
||||
}
|
||||
xfree (relptr);
|
||||
|
||||
/* Some of the first cards accidently don't set the
|
||||
CHANGE_FORCE_CHV bit but allow it anyway. */
|
||||
if (app->card_version <= 0x0100 && manufacturer == 1)
|
||||
app->app_local->extcap.change_force_chv = 1;
|
||||
|
||||
|
||||
if (opt.verbose > 1)
|
||||
dump_all_do (slot);
|
||||
|
||||
@ -1431,6 +1477,8 @@ app_select_openpgp (APP app)
|
||||
}
|
||||
|
||||
leave:
|
||||
if (rc)
|
||||
do_deinit (app);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
135
g10/card-util.c
135
g10/card-util.c
@ -43,39 +43,6 @@
|
||||
|
||||
#define CONTROL_D ('D' - 'A' + 1)
|
||||
|
||||
#if GNUPG_MAJOR_VERSION == 1
|
||||
#define GET_NBITS(a) mpi_get_nbits (a)
|
||||
#else
|
||||
#define GET_NBITS(a) gcry_mpi_get_nbits (a)
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
copy_mpi (MPI a, unsigned char *buffer, size_t len, size_t *ncopied)
|
||||
{
|
||||
int rc;
|
||||
#if GNUPG_MAJOR_VERSION == 1
|
||||
unsigned char *tmp;
|
||||
unsigned int n;
|
||||
|
||||
tmp = mpi_get_secure_buffer (a, &n, NULL);
|
||||
if (n > len)
|
||||
rc = G10ERR_GENERAL;
|
||||
else
|
||||
{
|
||||
rc = 0;
|
||||
memcpy (buffer, tmp, n);
|
||||
*ncopied = n;
|
||||
}
|
||||
xfree (tmp);
|
||||
#else /* GNUPG_MAJOR_VERSION != 1 */
|
||||
rc = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, len, ncopied, a);
|
||||
#endif /* GNUPG_MAJOR_VERSION != 1 */
|
||||
if (rc)
|
||||
log_error ("mpi_copy failed: %s\n", gpg_strerror (rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Change the PIN of a an OpenPGP card. This is an interactive
|
||||
function. */
|
||||
@ -897,10 +864,15 @@ generate_card_keys (const char *serialno)
|
||||
{
|
||||
struct agent_card_info_s info;
|
||||
int forced_chv1;
|
||||
int want_backup;
|
||||
|
||||
if (get_info_for_key_operation (&info))
|
||||
return;
|
||||
|
||||
want_backup = !(cpr_get_answer_is_yes
|
||||
( "cardedit.genkeys.backup_enc",
|
||||
_("Inhibit creation of encryption key backup? ")));
|
||||
|
||||
if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
|
||||
|| (info.fpr2valid && !fpr_is_zero (info.fpr2))
|
||||
|| (info.fpr3valid && !fpr_is_zero (info.fpr3)))
|
||||
@ -928,7 +900,8 @@ generate_card_keys (const char *serialno)
|
||||
if (check_pin_for_key_operation (&info, &forced_chv1))
|
||||
goto leave;
|
||||
|
||||
generate_keypair (NULL, info.serialno);
|
||||
generate_keypair (NULL, info.serialno,
|
||||
want_backup? opt.homedir:NULL);
|
||||
|
||||
leave:
|
||||
agent_release_card_info (&info);
|
||||
@ -1003,12 +976,6 @@ card_store_subkey (KBNODE node, int use)
|
||||
PKT_secret_key *copied_sk = NULL;
|
||||
PKT_secret_key *sk;
|
||||
size_t n;
|
||||
MPI rsa_n, rsa_e, rsa_p, rsa_q;
|
||||
unsigned int nbits;
|
||||
unsigned char *template = NULL;
|
||||
unsigned char *tp;
|
||||
unsigned char m[128], e[4];
|
||||
size_t mlen, elen;
|
||||
const char *s;
|
||||
int allow_keyno[3];
|
||||
|
||||
@ -1087,94 +1054,9 @@ card_store_subkey (KBNODE node, int use)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Some basic checks on the key parameters. */
|
||||
rsa_n = sk->skey[0];
|
||||
rsa_e = sk->skey[1];
|
||||
rsa_p = sk->skey[3];
|
||||
rsa_q = sk->skey[4];
|
||||
|
||||
nbits = GET_NBITS (rsa_n);
|
||||
if (nbits != 1024)
|
||||
{
|
||||
log_error (_("length of RSA modulus is not %d\n"), 1024);
|
||||
goto leave;
|
||||
}
|
||||
nbits = GET_NBITS (rsa_e);
|
||||
if (nbits < 2 || nbits > 32)
|
||||
{
|
||||
log_error (_("public exponent too large (more than 32 bits)\n"));
|
||||
goto leave;
|
||||
}
|
||||
nbits = GET_NBITS (rsa_p);
|
||||
if (nbits != 512)
|
||||
{
|
||||
log_error (_("length of an RSA prime is not %d\n"), 512);
|
||||
goto leave;
|
||||
}
|
||||
nbits = GET_NBITS (rsa_q);
|
||||
if (nbits != 512)
|
||||
{
|
||||
log_error (_("length of an RSA prime is not %d\n"), 512);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
|
||||
/* We need the modulus later to calculate the fingerprint. */
|
||||
rc = copy_mpi (rsa_n, m, 128, &n);
|
||||
rc = save_unprotected_key_to_card (sk, keyno);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n == 128);
|
||||
mlen = 128;
|
||||
|
||||
/* Build the private key template as described in section 4.3.3.6 of
|
||||
the OpenPGP card specs:
|
||||
0xC0 <length> public exponent
|
||||
0xC1 <length> prime p
|
||||
0xC2 <length> prime q
|
||||
*/
|
||||
template = tp = xmalloc_secure (1+2 + 1+1+4 + 1+1+(512/8) + 1+1+(512/8));
|
||||
*tp++ = 0xC0;
|
||||
*tp++ = 4;
|
||||
rc = copy_mpi (rsa_e, tp, 4, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n <= 4);
|
||||
memcpy (e, tp, n); /* Save a copy of the exponent for later use. */
|
||||
elen = n;
|
||||
if (n != 4)
|
||||
{
|
||||
memmove (tp+4-n, tp, 4-n);
|
||||
memset (tp, 0, 4-n);
|
||||
}
|
||||
tp += 4;
|
||||
|
||||
*tp++ = 0xC1;
|
||||
*tp++ = 64;
|
||||
rc = copy_mpi (rsa_p, tp, 64, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n == 64);
|
||||
tp += 64;
|
||||
|
||||
*tp++ = 0xC2;
|
||||
*tp++ = 64;
|
||||
rc = copy_mpi (rsa_q, tp, 64, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n == 64);
|
||||
tp += 64;
|
||||
assert (tp - template == 138);
|
||||
|
||||
rc = agent_openpgp_storekey (keyno,
|
||||
template, tp - template,
|
||||
sk->timestamp,
|
||||
m, mlen,
|
||||
e, elen);
|
||||
|
||||
if (rc)
|
||||
goto leave;
|
||||
xfree (template);
|
||||
template = NULL;
|
||||
|
||||
/* Get back to the maybe protected original secret key. */
|
||||
if (copied_sk)
|
||||
@ -1205,7 +1087,6 @@ card_store_subkey (KBNODE node, int use)
|
||||
leave:
|
||||
if (copied_sk)
|
||||
free_secret_key (copied_sk);
|
||||
xfree (template);
|
||||
agent_release_card_info (&info);
|
||||
return okay;
|
||||
}
|
||||
|
@ -3181,12 +3181,12 @@ main( int argc, char **argv )
|
||||
if( opt.batch ) {
|
||||
if( argc > 1 )
|
||||
wrong_args("--gen-key [parameterfile]");
|
||||
generate_keypair( argc? *argv : NULL, NULL );
|
||||
generate_keypair( argc? *argv : NULL, NULL, NULL );
|
||||
}
|
||||
else {
|
||||
if( argc )
|
||||
wrong_args("--gen-key");
|
||||
generate_keypair(NULL, NULL);
|
||||
generate_keypair(NULL, NULL, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
673
g10/keygen.c
673
g10/keygen.c
@ -63,7 +63,8 @@ enum para_name {
|
||||
pPASSPHRASE,
|
||||
pPASSPHRASE_DEK,
|
||||
pPASSPHRASE_S2K,
|
||||
pSERIALNO
|
||||
pSERIALNO,
|
||||
pBACKUPENCDIR
|
||||
};
|
||||
|
||||
struct para_data_s {
|
||||
@ -120,6 +121,47 @@ static int write_keyblock( IOBUF out, KBNODE node );
|
||||
static int gen_card_key (int algo, int keyno, int is_primary,
|
||||
KBNODE pub_root, KBNODE sec_root,
|
||||
u32 expireval, struct para_data_s *para);
|
||||
static int gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
||||
KBNODE pub_root, KBNODE sec_root,
|
||||
u32 expireval, struct para_data_s *para,
|
||||
const char *backup_dir);
|
||||
|
||||
|
||||
#if GNUPG_MAJOR_VERSION == 1
|
||||
#define GET_NBITS(a) mpi_get_nbits (a)
|
||||
#else
|
||||
#define GET_NBITS(a) gcry_mpi_get_nbits (a)
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
copy_mpi (MPI a, unsigned char *buffer, size_t len, size_t *ncopied)
|
||||
{
|
||||
int rc;
|
||||
#if GNUPG_MAJOR_VERSION == 1
|
||||
unsigned char *tmp;
|
||||
unsigned int n;
|
||||
|
||||
tmp = mpi_get_secure_buffer (a, &n, NULL);
|
||||
if (n > len)
|
||||
rc = G10ERR_GENERAL;
|
||||
else
|
||||
{
|
||||
rc = 0;
|
||||
memcpy (buffer, tmp, n);
|
||||
*ncopied = n;
|
||||
}
|
||||
xfree (tmp);
|
||||
#else /* GNUPG_MAJOR_VERSION != 1 */
|
||||
rc = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, len, ncopied, a);
|
||||
#endif /* GNUPG_MAJOR_VERSION != 1 */
|
||||
if (rc)
|
||||
log_error ("mpi_copy failed: %s\n", gpg_strerror (rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
write_uid( KBNODE root, const char *s )
|
||||
@ -1622,6 +1664,7 @@ ask_user_id( int mode )
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: We need a way to cancel this prompt. */
|
||||
static DEK *
|
||||
do_ask_passphrase( STRING2KEY **ret_s2k )
|
||||
{
|
||||
@ -2213,10 +2256,14 @@ read_parameter_file( const char *fname )
|
||||
/*
|
||||
* Generate a keypair (fname is only used in batch mode) If
|
||||
* CARD_SERIALNO is not NULL the fucntion will create the keys on an
|
||||
* OpenPGP Card.
|
||||
* OpenPGP Card. If BACKUP_ENCRYPTION_DIR has been set and
|
||||
* CARD_SERIALNO is NOT NULL, the encryption key for the card gets
|
||||
* generate in software, imported to the card and a backup file
|
||||
* written to directory given by this argument .
|
||||
*/
|
||||
void
|
||||
generate_keypair( const char *fname, const char *card_serialno )
|
||||
generate_keypair (const char *fname, const char *card_serialno,
|
||||
const char *backup_encryption_dir)
|
||||
{
|
||||
unsigned int nbits;
|
||||
char *uid = NULL;
|
||||
@ -2239,158 +2286,245 @@ generate_keypair( const char *fname, const char *card_serialno )
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt.batch)
|
||||
{
|
||||
read_parameter_file( fname );
|
||||
return;
|
||||
}
|
||||
if (opt.batch)
|
||||
{
|
||||
read_parameter_file( fname );
|
||||
return;
|
||||
}
|
||||
|
||||
if (card_serialno)
|
||||
{
|
||||
if (card_serialno)
|
||||
{
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
r = xcalloc (1, sizeof *r + strlen (card_serialno) );
|
||||
r->key = pSERIALNO;
|
||||
strcpy( r->u.value, card_serialno);
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = xcalloc (1, sizeof *r + strlen (card_serialno) );
|
||||
r->key = pSERIALNO;
|
||||
strcpy( r->u.value, card_serialno);
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
algo = PUBKEY_ALGO_RSA;
|
||||
algo = PUBKEY_ALGO_RSA;
|
||||
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYUSAGE;
|
||||
strcpy (r->u.value, "sign");
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYUSAGE;
|
||||
strcpy (r->u.value, "sign");
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pSUBKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pSUBKEYUSAGE;
|
||||
strcpy (r->u.value, "encrypt");
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pSUBKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pSUBKEYUSAGE;
|
||||
strcpy (r->u.value, "encrypt");
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pAUTHKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pAUTHKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
if (backup_encryption_dir)
|
||||
{
|
||||
r = xcalloc (1, sizeof *r + strlen (backup_encryption_dir) );
|
||||
r->key = pBACKUPENCDIR;
|
||||
strcpy (r->u.value, backup_encryption_dir);
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
#endif /*ENABLE_CARD_SUPPORT*/
|
||||
}
|
||||
else
|
||||
{
|
||||
algo = ask_algo( 0, &use );
|
||||
if( !algo )
|
||||
{ /* default: DSA with ElG subkey of the specified size */
|
||||
both = 1;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA );
|
||||
r->next = para;
|
||||
para = r;
|
||||
tty_printf(_("DSA keypair will have 1024 bits.\n"));
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYLENGTH;
|
||||
strcpy( r->u.value, "1024" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYUSAGE;
|
||||
strcpy( r->u.value, "sign" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
algo = ask_algo( 0, &use );
|
||||
if( !algo )
|
||||
{ /* default: DSA with ElG subkey of the specified size */
|
||||
both = 1;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA );
|
||||
r->next = para;
|
||||
para = r;
|
||||
tty_printf(_("DSA keypair will have 1024 bits.\n"));
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYLENGTH;
|
||||
strcpy( r->u.value, "1024" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYUSAGE;
|
||||
strcpy( r->u.value, "sign" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
algo = PUBKEY_ALGO_ELGAMAL_E;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pSUBKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pSUBKEYUSAGE;
|
||||
strcpy( r->u.value, "encrypt" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
algo = PUBKEY_ALGO_ELGAMAL_E;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pSUBKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pSUBKEYUSAGE;
|
||||
strcpy( r->u.value, "encrypt" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
if (use)
|
||||
{
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYUSAGE;
|
||||
sprintf( r->u.value, "%s%s",
|
||||
(use & PUBKEY_USAGE_SIG)? "sign ":"",
|
||||
(use & PUBKEY_USAGE_ENC)? "encrypt ":"" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
if (use)
|
||||
{
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYUSAGE;
|
||||
sprintf( r->u.value, "%s%s",
|
||||
(use & PUBKEY_USAGE_SIG)? "sign ":"",
|
||||
(use & PUBKEY_USAGE_ENC)? "encrypt ":"" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
nbits = ask_keysize( algo );
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
|
||||
sprintf( r->u.value, "%u", nbits);
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
nbits = ask_keysize( algo );
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
|
||||
sprintf( r->u.value, "%u", nbits);
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
|
||||
expire = ask_expire_interval(0);
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYEXPIRE;
|
||||
r->u.expire = expire;
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pSUBKEYEXPIRE;
|
||||
r->u.expire = expire;
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
expire = ask_expire_interval(0);
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pKEYEXPIRE;
|
||||
r->u.expire = expire;
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = m_alloc_clear( sizeof *r + 20 );
|
||||
r->key = pSUBKEYEXPIRE;
|
||||
r->u.expire = expire;
|
||||
r->next = para;
|
||||
para = r;
|
||||
uid = ask_user_id(0);
|
||||
if( !uid )
|
||||
{
|
||||
log_error(_("Key generation canceled.\n"));
|
||||
release_parameter_list( para );
|
||||
return;
|
||||
}
|
||||
r = m_alloc_clear( sizeof *r + strlen(uid) );
|
||||
r->key = pUSERID;
|
||||
strcpy( r->u.value, uid );
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
dek = card_serialno? NULL : do_ask_passphrase( &s2k );
|
||||
if( dek )
|
||||
{
|
||||
r = m_alloc_clear( sizeof *r );
|
||||
r->key = pPASSPHRASE_DEK;
|
||||
r->u.dek = dek;
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = m_alloc_clear( sizeof *r );
|
||||
r->key = pPASSPHRASE_S2K;
|
||||
r->u.s2k = s2k;
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
|
||||
proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno);
|
||||
release_parameter_list( para );
|
||||
}
|
||||
|
||||
uid = ask_user_id(0);
|
||||
if( !uid )
|
||||
{
|
||||
log_error(_("Key generation canceled.\n"));
|
||||
release_parameter_list( para );
|
||||
return;
|
||||
}
|
||||
r = m_alloc_clear( sizeof *r + strlen(uid) );
|
||||
r->key = pUSERID;
|
||||
strcpy( r->u.value, uid );
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
dek = card_serialno? NULL : do_ask_passphrase( &s2k );
|
||||
if( dek )
|
||||
{
|
||||
r = m_alloc_clear( sizeof *r );
|
||||
r->key = pPASSPHRASE_DEK;
|
||||
r->u.dek = dek;
|
||||
r->next = para;
|
||||
para = r;
|
||||
r = m_alloc_clear( sizeof *r );
|
||||
r->key = pPASSPHRASE_S2K;
|
||||
r->u.s2k = s2k;
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
|
||||
proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno);
|
||||
release_parameter_list( para );
|
||||
|
||||
/* Generate a raw key and return it as a secret key packet. The
|
||||
function will ask for the passphrase and return a protected as well
|
||||
as an unprotected copy of a new secret key packet. 0 is returned
|
||||
on success and the caller must then free the returned values. */
|
||||
static int
|
||||
generate_raw_key (int algo, unsigned int nbits, u32 created_at,
|
||||
PKT_secret_key **r_sk_unprotected,
|
||||
PKT_secret_key **r_sk_protected)
|
||||
{
|
||||
int rc;
|
||||
DEK *dek = NULL;
|
||||
STRING2KEY *s2k = NULL;
|
||||
PKT_secret_key *sk = NULL;
|
||||
int i;
|
||||
size_t nskey, npkey;
|
||||
|
||||
npkey = pubkey_get_npkey (algo);
|
||||
nskey = pubkey_get_nskey (algo);
|
||||
assert (nskey <= PUBKEY_MAX_NSKEY && npkey < nskey);
|
||||
|
||||
if (nbits < 512)
|
||||
{
|
||||
nbits = 512;
|
||||
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
||||
}
|
||||
|
||||
if ((nbits % 32))
|
||||
{
|
||||
nbits = ((nbits + 31) / 32) * 32;
|
||||
log_info(_("keysize rounded up to %u bits\n"), nbits );
|
||||
}
|
||||
|
||||
dek = do_ask_passphrase (&s2k);
|
||||
|
||||
sk = m_alloc_clear (sizeof *sk);
|
||||
sk->timestamp = created_at;
|
||||
sk->version = 4;
|
||||
sk->pubkey_algo = algo;
|
||||
|
||||
rc = pubkey_generate (algo, nbits, sk->skey, NULL);
|
||||
if (rc)
|
||||
{
|
||||
log_error("pubkey_generate failed: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
for (i=npkey; i < nskey; i++)
|
||||
sk->csum += checksum_mpi (sk->skey[i]);
|
||||
|
||||
if (r_sk_unprotected)
|
||||
*r_sk_unprotected = copy_secret_key (NULL, sk);
|
||||
|
||||
if (dek)
|
||||
{
|
||||
sk->protect.algo = dek->algo;
|
||||
sk->protect.s2k = *s2k;
|
||||
rc = protect_secret_key (sk, dek);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("protect_secret_key failed: %s\n", g10_errstr(rc));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
if (r_sk_protected)
|
||||
{
|
||||
*r_sk_protected = sk;
|
||||
sk = NULL;
|
||||
}
|
||||
|
||||
leave:
|
||||
if (sk)
|
||||
free_secret_key (sk);
|
||||
m_free (dek);
|
||||
m_free (s2k);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -2552,8 +2686,20 @@ do_generate_keypair( struct para_data_s *para,
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root,
|
||||
get_parameter_u32 (para, pKEYEXPIRE), para);
|
||||
if ((s = get_parameter_value (para, pBACKUPENCDIR)))
|
||||
{
|
||||
/* A backup of the encryption key has been requested.
|
||||
Generate the key i software and import it then to
|
||||
the card. Write a backup file. */
|
||||
rc = gen_card_key_with_backup (PUBKEY_ALGO_RSA, 2, 0,
|
||||
pub_root, sec_root,
|
||||
get_parameter_u32 (para,
|
||||
pKEYEXPIRE),
|
||||
para, s);
|
||||
}
|
||||
else
|
||||
rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root,
|
||||
get_parameter_u32 (para, pKEYEXPIRE), para);
|
||||
}
|
||||
|
||||
if( !rc )
|
||||
@ -2943,6 +3089,7 @@ gen_card_key (int algo, int keyno, int is_primary,
|
||||
PKT_public_key *pk;
|
||||
|
||||
assert (algo == PUBKEY_ALGO_RSA);
|
||||
|
||||
|
||||
rc = agent_scd_genkey (&info, keyno, 1);
|
||||
/* if (gpg_err_code (rc) == GPG_ERR_EEXIST) */
|
||||
@ -3006,3 +3153,241 @@ gen_card_key (int algo, int keyno, int is_primary,
|
||||
return -1;
|
||||
#endif /*!ENABLE_CARD_SUPPORT*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
||||
KBNODE pub_root, KBNODE sec_root,
|
||||
u32 expireval, struct para_data_s *para,
|
||||
const char *backup_dir)
|
||||
{
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
int rc;
|
||||
const char *s;
|
||||
PACKET *pkt;
|
||||
PKT_secret_key *sk, *sk_unprotected, *sk_protected;
|
||||
PKT_public_key *pk;
|
||||
size_t n;
|
||||
int i;
|
||||
|
||||
rc = generate_raw_key (algo, 1024, make_timestamp (),
|
||||
&sk_unprotected, &sk_protected);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* First, store the key to the card. */
|
||||
rc = save_unprotected_key_to_card (sk_unprotected, keyno);
|
||||
if (rc)
|
||||
{
|
||||
log_error (_("storing key onto card failed: %s\n"), g10_errstr (rc));
|
||||
free_secret_key (sk_unprotected);
|
||||
free_secret_key (sk_protected);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Get rid of the secret key parameters and store the serial numer. */
|
||||
sk = sk_unprotected;
|
||||
n = pubkey_get_nskey (sk->pubkey_algo);
|
||||
for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++)
|
||||
{
|
||||
mpi_free (sk->skey[i]);
|
||||
sk->skey[i] = NULL;
|
||||
}
|
||||
i = pubkey_get_npkey (sk->pubkey_algo);
|
||||
sk->skey[i] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10);
|
||||
sk->is_protected = 1;
|
||||
sk->protect.s2k.mode = 1002;
|
||||
s = get_parameter_value (para, pSERIALNO);
|
||||
assert (s);
|
||||
for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1];
|
||||
sk->protect.ivlen++, s += 2)
|
||||
sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s);
|
||||
|
||||
/* Now write the *protected* secret key to the file. */
|
||||
{
|
||||
char name_buffer[50];
|
||||
char *fname;
|
||||
IOBUF fp;
|
||||
mode_t oldmask;
|
||||
|
||||
keyid_from_sk (sk, NULL);
|
||||
sprintf (name_buffer,"sk_%08lX%08lX.gpg",
|
||||
(ulong)sk->keyid[0], (ulong)sk->keyid[1]);
|
||||
|
||||
fname = make_filename (backup_dir, name_buffer, NULL);
|
||||
oldmask = umask (077);
|
||||
fp = iobuf_create (fname);
|
||||
umask (oldmask);
|
||||
if (!fp)
|
||||
{
|
||||
log_error (_("can't create backup file `%s': %s\n"),
|
||||
fname, strerror(errno) );
|
||||
m_free (fname);
|
||||
free_secret_key (sk_unprotected);
|
||||
free_secret_key (sk_protected);
|
||||
return G10ERR_OPEN_FILE;
|
||||
}
|
||||
|
||||
pkt = xcalloc (1, sizeof *pkt);
|
||||
pkt->pkttype = PKT_SECRET_KEY;
|
||||
pkt->pkt.secret_key = sk_protected;
|
||||
sk_protected = NULL;
|
||||
|
||||
rc = build_packet (fp, pkt);
|
||||
if (rc)
|
||||
{
|
||||
log_error("build packet failed: %s\n", g10_errstr(rc) );
|
||||
iobuf_cancel (fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
iobuf_close (fp);
|
||||
iobuf_ioctl (NULL, 2, 0, (char*)fname);
|
||||
log_info (_("NOTE: backup of card key saved to `%s'\n"), fname);
|
||||
}
|
||||
free_packet (pkt);
|
||||
m_free (pkt);
|
||||
m_free (fname);
|
||||
if (rc)
|
||||
{
|
||||
free_secret_key (sk_unprotected);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the public key from the secret key. */
|
||||
pk = xcalloc (1, sizeof *pk );
|
||||
pk->timestamp = sk->timestamp;
|
||||
pk->version = sk->version;
|
||||
if (expireval)
|
||||
pk->expiredate = sk->expiredate = sk->timestamp + expireval;
|
||||
pk->pubkey_algo = sk->pubkey_algo;
|
||||
n = pubkey_get_npkey (sk->pubkey_algo);
|
||||
for (i=0; i < n; i++)
|
||||
pk->pkey[i] = mpi_copy (sk->skey[i]);
|
||||
|
||||
/* Build packets and add them to the node lists. */
|
||||
pkt = xcalloc (1,sizeof *pkt);
|
||||
pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
|
||||
pkt->pkt.public_key = pk;
|
||||
add_kbnode(pub_root, new_kbnode( pkt ));
|
||||
|
||||
pkt = xcalloc (1,sizeof *pkt);
|
||||
pkt->pkttype = is_primary ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY;
|
||||
pkt->pkt.secret_key = sk;
|
||||
add_kbnode(sec_root, new_kbnode( pkt ));
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif /*!ENABLE_CARD_SUPPORT*/
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
int
|
||||
save_unprotected_key_to_card (PKT_secret_key *sk, int keyno)
|
||||
{
|
||||
int rc;
|
||||
size_t n;
|
||||
MPI rsa_n, rsa_e, rsa_p, rsa_q;
|
||||
unsigned int nbits;
|
||||
unsigned char *template = NULL;
|
||||
unsigned char *tp;
|
||||
unsigned char m[128], e[4];
|
||||
size_t mlen, elen;
|
||||
|
||||
assert (is_RSA (sk->pubkey_algo));
|
||||
assert (!sk->is_protected);
|
||||
|
||||
rc = -1;
|
||||
/* Some basic checks on the key parameters. */
|
||||
rsa_n = sk->skey[0];
|
||||
rsa_e = sk->skey[1];
|
||||
rsa_p = sk->skey[3];
|
||||
rsa_q = sk->skey[4];
|
||||
|
||||
nbits = GET_NBITS (rsa_n);
|
||||
if (nbits != 1024)
|
||||
{
|
||||
log_error (_("length of RSA modulus is not %d\n"), 1024);
|
||||
goto leave;
|
||||
}
|
||||
nbits = GET_NBITS (rsa_e);
|
||||
if (nbits < 2 || nbits > 32)
|
||||
{
|
||||
log_error (_("public exponent too large (more than 32 bits)\n"));
|
||||
goto leave;
|
||||
}
|
||||
nbits = GET_NBITS (rsa_p);
|
||||
if (nbits != 512)
|
||||
{
|
||||
log_error (_("length of an RSA prime is not %d\n"), 512);
|
||||
goto leave;
|
||||
}
|
||||
nbits = GET_NBITS (rsa_q);
|
||||
if (nbits != 512)
|
||||
{
|
||||
log_error (_("length of an RSA prime is not %d\n"), 512);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
|
||||
/* We need the modulus later to calculate the fingerprint. */
|
||||
rc = copy_mpi (rsa_n, m, 128, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n == 128);
|
||||
mlen = 128;
|
||||
|
||||
/* Build the private key template as described in section 4.3.3.6 of
|
||||
the OpenPGP card specs:
|
||||
0xC0 <length> public exponent
|
||||
0xC1 <length> prime p
|
||||
0xC2 <length> prime q
|
||||
*/
|
||||
template = tp = xmalloc_secure (1+2 + 1+1+4 + 1+1+(512/8) + 1+1+(512/8));
|
||||
*tp++ = 0xC0;
|
||||
*tp++ = 4;
|
||||
rc = copy_mpi (rsa_e, tp, 4, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n <= 4);
|
||||
memcpy (e, tp, n); /* Save a copy of the exponent for later use. */
|
||||
elen = n;
|
||||
if (n != 4)
|
||||
{
|
||||
memmove (tp+4-n, tp, 4-n);
|
||||
memset (tp, 0, 4-n);
|
||||
}
|
||||
tp += 4;
|
||||
|
||||
*tp++ = 0xC1;
|
||||
*tp++ = 64;
|
||||
rc = copy_mpi (rsa_p, tp, 64, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n == 64);
|
||||
tp += 64;
|
||||
|
||||
*tp++ = 0xC2;
|
||||
*tp++ = 64;
|
||||
rc = copy_mpi (rsa_q, tp, 64, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n == 64);
|
||||
tp += 64;
|
||||
assert (tp - template == 138);
|
||||
|
||||
rc = agent_openpgp_storekey (keyno,
|
||||
template, tp - template,
|
||||
sk->timestamp,
|
||||
m, mlen,
|
||||
e, elen);
|
||||
|
||||
leave:
|
||||
xfree (template);
|
||||
return rc;
|
||||
}
|
||||
#endif /*ENABLE_CARD_SUPPORT*/
|
||||
|
@ -153,7 +153,8 @@ void show_basic_key_info (KBNODE keyblock);
|
||||
/*-- keygen.c --*/
|
||||
u32 ask_expire_interval(int object);
|
||||
u32 ask_expiredate(void);
|
||||
void generate_keypair( const char *fname, const char *card_serialno );
|
||||
void generate_keypair( const char *fname, const char *card_serialno,
|
||||
const char *backup_encryption_dir );
|
||||
int keygen_set_std_prefs (const char *string,int personal);
|
||||
PKT_user_id *keygen_get_std_prefs (void);
|
||||
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
|
||||
@ -165,6 +166,7 @@ int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
|
||||
int keyno, const char *serialno);
|
||||
int save_unprotected_key_to_card (PKT_secret_key *sk, int keyno);
|
||||
#endif
|
||||
|
||||
/*-- openfile.c --*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user