* cardglue.c (pin_cb): Detect whether an admin or regular PIN is

requested.
(genkey_status_cb): New.
(agent_scd_genkey): Implemented.

* keygen.c (generate_keypair): New arg CARD_SERIALNO and prepare
parameters for on card key generation. Changed all callers.
(do_generate_keypair): Add new arg card and merged casrd specific
changes from 1.9.
(proc_parameter_file): New arg card, apss it down to
do_generate_keypair and changed all callers.
(gen_card_key): New.

* g10.c: Include cardclue.h.
(main): s/app_set_default_reader_port/card_set_reader_port/.
* cardglue.c (card_set_reader_port): New to address include file
issues.
This commit is contained in:
Werner Koch 2003-10-08 15:21:20 +00:00
parent fcbd46e070
commit 72c648c035
11 changed files with 550 additions and 145 deletions

View File

@ -1,3 +1,23 @@
2003-10-08 Werner Koch <wk@gnupg.org>
* cardglue.c (pin_cb): Detect whether an admin or regular PIN is
requested.
(genkey_status_cb): New.
(agent_scd_genkey): Implemented.
* keygen.c (generate_keypair): New arg CARD_SERIALNO and prepare
parameters for on card key generation. Changed all callers.
(do_generate_keypair): Add new arg card and merged casrd specific
changes from 1.9.
(proc_parameter_file): New arg card, apss it down to
do_generate_keypair and changed all callers.
(gen_card_key): New.
* g10.c: Include cardclue.h.
(main): s/app_set_default_reader_port/card_set_reader_port/.
* cardglue.c (card_set_reader_port): New to address include file
issues.
2003-10-02 Werner Koch <wk@gnupg.org>
* cardglue.c (learn_status_cb): Release values before assignment

View File

@ -142,12 +142,16 @@ install-data-local:
# Helper to update some source files.
update-source-from-gnupg-2:
test -d ../../gnupg-1.9/scd
@for i in $(card_support_source_scd); do \
cp ../../gnupg-1.9/scd/$$i $$i; echo $$i; \
done
@for i in $(card_support_source_g10); do \
cp ../../gnupg-1.9/g10/$$i $$i; echo $$i; \
done
@echo "Please remember to update the ChangeLog accordingly!"
@set -e; \
if test -d ../../gnupg-1.9/scd; then dir="../../gnupg-1.9"; \
elif test -d ../../gnupg/scd; then dir="../../gnupg"; \
else exit 1; \
fi; \
for i in $(card_support_source_scd); do \
cp $$dir/scd/$$i $$i; echo $$i; \
done ;\
for i in $(card_support_source_g10); do \
cp $$dir/g10/$$i $$i; echo $$i; \
done ; \
echo "Please remember to update the ChangeLog accordingly!"

View File

@ -425,6 +425,8 @@ do_getattr (APP app, CTRL ctrl, const char *name)
{ "CA-FPR", 0x00C6, 3 },
{ "CHV-STATUS", 0x00C4, 1 },
{ "SIG-COUNTER", 0x0093, 2 },
{ "SERIALNO", 0x004F, -1 },
{ "AID", 0x004F },
{ NULL, 0 }
};
int idx, i;
@ -437,6 +439,29 @@ do_getattr (APP app, CTRL ctrl, const char *name)
if (!table[idx].name)
return gpg_error (GPG_ERR_INV_NAME);
if (table[idx].special == -1)
{
/* The serial number is very special. We could have used the
AID DO to retrieve it, but we have it already in the app
context and the stanmp argument is required anyway which we
can't by other means. The AID DO is available anyway but not
hex formatted. */
char *serial;
time_t stamp;
char tmp[50];
if (!app_get_serial_and_stamp (app, &serial, &stamp))
{
sprintf (tmp, "%lu", (unsigned long)stamp);
send_status_info (ctrl, "SERIALNO",
serial, strlen (serial),
tmp, strlen (tmp),
NULL, 0);
xfree (serial);
}
return 0;
}
relptr = get_one_do (app->slot, table[idx].tag, &value, &valuelen);
if (relptr)
{

View File

@ -241,6 +241,17 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name)
tty_fprintf (fp, "\n");
}
/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
static int
fpr_is_zero (const char *fpr)
{
int i;
for (i=0; i < 20 && !fpr[i]; i++)
;
return (i == 20);
}
/* Print all available information about the current card. */
void
@ -569,6 +580,76 @@ toggle_forcesig (void)
}
static void
generate_card_keys (void)
{
struct agent_card_info_s info;
int rc;
int forced_chv1;
memset (&info, 0, sizeof info);
rc = agent_scd_getattr ("KEY-FPR", &info);
if (!rc)
rc = agent_scd_getattr ("SERIALNO", &info);
if (!rc)
rc = agent_scd_getattr ("CHV-STATUS", &info);
if (!rc)
rc = agent_scd_getattr ("DISP-NAME", &info);
if (rc)
{
log_error ("error getting current key info: %s\n", gpg_strerror (rc));
return;
}
if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
|| (info.fpr2valid && !fpr_is_zero (info.fpr2))
|| (info.fpr3valid && !fpr_is_zero (info.fpr3)))
{
tty_printf ("\n");
log_info ("NOTE: keys are already stored on the card!\n");
tty_printf ("\n");
if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_keys",
_("Replace existing keys? ")))
{
agent_release_card_info (&info);
return;
}
}
else if (!info.disp_name || !*info.disp_name)
{
tty_printf ("\n");
tty_printf (_("Please note that the factory settings of the PINs are\n"
" PIN = \"%s\" Admin PIN = \"%s\"\n"
"You should change them using the command --change-pin\n"),
"123456", "12345678");
tty_printf ("\n");
}
forced_chv1 = !info.chv1_cached;
if (forced_chv1)
{ /* Switch of the forced mode so that during key generation we
don't get bothered with PIN queries for each
self-signature. */
rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1);
if (rc)
{
log_error ("error clearing forced signature PIN flag: %s\n",
gpg_strerror (rc));
return;
}
}
generate_keypair (NULL, info.serialno);
agent_release_card_info (&info);
if (forced_chv1)
{ /* Switch back to forced state. */
rc = agent_scd_setattr ("CHV-STATUS-1", "", 1);
if (rc)
{
log_error ("error setting forced signature PIN flag: %s\n",
gpg_strerror (rc));
return;
}
}
}
/* Menu to edit all user changeable values on an OpenPGP card. Only
Key creation is not handled here. */
@ -579,7 +660,7 @@ card_edit (STRLIST commands)
cmdNOP = 0,
cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG,
cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX,
cmdFORCESIG,
cmdFORCESIG, cmdGENERATE,
cmdINVCMD
};
@ -601,6 +682,7 @@ card_edit (STRLIST commands)
{ N_("lang") , cmdLANG , N_("change the language preferences") },
{ N_("sex") , cmdSEX , N_("change card holder's sex") },
{ N_("forcesig"), cmdFORCESIG, N_("toggle the signature force PIN flag") },
{ N_("generate"), cmdGENERATE, N_("generate new keys") },
{ NULL, cmdINVCMD }
};
@ -725,6 +807,10 @@ card_edit (STRLIST commands)
toggle_forcesig ();
break;
case cmdGENERATE:
generate_card_keys ();
break;
case cmdQUIT:
goto leave;

View File

@ -184,6 +184,13 @@ app_set_default_reader_port (const char *portstr)
}
void
card_set_reader_port (const char *portstr)
{
app_set_default_reader_port (portstr);
}
/* Retrieve the serial number and the time of the last update of the
card. The serial number is returned as a malloced string (hex
encoded) in SERIAL and the time of update is returned in STAMP. If
@ -493,7 +500,10 @@ pin_cb (void *opaque, const char *info, char **retstr)
*retstr = NULL;
log_debug ("asking for PIN '%s'\n", info);
value = ask_passphrase (info, "Enter PIN: ", &canceled);
value = ask_passphrase (info,
info && strstr (info, "dmin")?
_("Enter Admin PIN: ") : _("Enter PIN: "),
&canceled);
if (!value && canceled)
return -1;
else if (!value)
@ -519,19 +529,86 @@ agent_scd_setattr (const char *name,
return app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
}
static int
genkey_status_cb (void *opaque, const char *line)
{
struct agent_card_genkey_s *parm = opaque;
const char *keyword = line;
int keywordlen;
log_debug ("got status line `%s'\n", line);
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
;
while (spacep (line))
line++;
if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
{
parm->fprvalid = unhexify_fpr (line, parm->fpr);
}
if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
{
MPI a;
const char *name = line;
char *buf;
while (!spacep (line))
line++;
while (spacep (line))
line++;
buf = xmalloc ( 2 + strlen (line) + 1);
strcpy (stpcpy (buf, "0x"), line);
a = mpi_alloc (300);
if( mpi_fromstr (a, buf) )
log_error ("error parsing received key data\n");
else if (*name == 'n' && spacep (name+1))
parm->n = a;
else if (*name == 'e' && spacep (name+1))
parm->e = a;
else
{
log_info ("unknown parameter name in received key data\n");
mpi_free (a);
}
xfree (buf);
}
else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
{
parm->created_at = (u32)strtoul (line, NULL, 10);
}
return 0;
}
/* Send a GENKEY command to the SCdaemon. */
int
agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
{
APP app;
char keynostr[20];
struct ctrl_ctx_s ctrl;
return gpg_error (GPG_ERR_CARD);
app = current_app? current_app : open_card ();
if (!app)
return gpg_error (GPG_ERR_CARD);
memset (info, 0, sizeof *info);
sprintf (keynostr, "%d", keyno);
ctrl.status_cb = genkey_status_cb;
ctrl.status_cb_arg = info;
return app->fnc.genkey (app, &ctrl, keynostr,
force? 1:0,
pin_cb, NULL);
}
/* Send a PKSIGN command to the SCdaemon. */
int
agent_scd_pksign (const char *serialno, int hashalgo,
const unsigned char *indata, size_t indatalen,
char **r_buf, size_t *r_buflen)
unsigned char **r_buf, size_t *r_buflen)
{
APP app;

View File

@ -67,6 +67,7 @@ typedef struct app_ctx_s *APP;
typedef struct ctrl_ctx_s *CTRL;
#define GPG_ERR_GENERAL G10ERR_GENERAL
#define GPG_ERR_BAD_PIN G10ERR_BAD_PASS
#define GPG_ERR_CARD G10ERR_GENERAL
#define GPG_ERR_EEXIST G10ERR_FILE_EXISTS
@ -107,6 +108,8 @@ typedef int gpg_err_code_t;
#define gnupg_get_time() make_timestamp ()
void card_set_reader_port (const char *portstr);
char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
PKT_secret_key *sk);
void send_status_info (CTRL ctrl, const char *keyword, ...);
@ -143,7 +146,7 @@ int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force);
/* Send a PKSIGN command to the SCdaemon. */
int agent_scd_pksign (const char *keyid, int hashalgo,
const unsigned char *indata, size_t indatalen,
char **r_buf, size_t *r_buflen);
unsigned char **r_buf, size_t *r_buflen);
/* Send a PKDECRYPT command to the SCdaemon. */
int agent_scd_pkdecrypt (const char *serialno,

View File

@ -51,6 +51,7 @@
#include "g10defs.h"
#include "keyserver-internal.h"
#include "exec.h"
#include "cardglue.h"
enum cmd_and_opt_values
{
@ -1425,7 +1426,7 @@ main( int argc, char **argv )
case aCardEdit: set_cmd (&cmd, aCardEdit); break;
case aChangePIN: set_cmd (&cmd, aChangePIN); break;
case oReaderPort:
app_set_default_reader_port (pargs.r.ret_str);
card_set_reader_port (pargs.r.ret_str);
break;
case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break;
@ -2603,12 +2604,12 @@ main( int argc, char **argv )
if( opt.batch ) {
if( argc > 1 )
wrong_args("--gen-key [parameterfile]");
generate_keypair( argc? *argv : NULL );
generate_keypair( argc? *argv : NULL, NULL );
}
else {
if( argc )
wrong_args("--gen-key");
generate_keypair(NULL);
generate_keypair(NULL, NULL);
}
break;

View File

@ -385,9 +385,9 @@ void rndlinux_constructor(void) {}
/* Stubs to avoid linking to ../util/ttyio.c */
int tty_batchmode( int onoff ) { return 0; }
void tty_printf( const char *fmt, ... ) { }
void tty_print_string( byte *p, size_t n ) { }
void tty_print_utf8_string( byte *p, size_t n ) {}
void tty_print_utf8_string2( byte *p, size_t n, size_t max_n ) {}
void tty_print_string( const byte *p, size_t n ) { }
void tty_print_utf8_string( const byte *p, size_t n ) {}
void tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) {}
char *tty_get( const char *prompt ) { return NULL;}
char *tty_get_hidden( const char *prompt ) {return NULL; }
void tty_kill_prompt(void) {}

View File

@ -36,6 +36,7 @@
#include "trustdb.h"
#include "status.h"
#include "i18n.h"
#include "cardglue.h"
#define MAX_PREFS 30
@ -46,6 +47,7 @@ enum para_name {
pSUBKEYTYPE,
pSUBKEYLENGTH,
pSUBKEYUSAGE,
pAUTHKEYTYPE,
pNAMEREAL,
pNAMEEMAIL,
pNAMECOMMENT,
@ -57,7 +59,8 @@ enum para_name {
pSUBKEYEXPIRE, /* in n seconds */
pPASSPHRASE,
pPASSPHRASE_DEK,
pPASSPHRASE_S2K
pPASSPHRASE_S2K,
pSERIALNO
};
struct para_data_s {
@ -109,9 +112,12 @@ static int nzip_prefs;
static int mdc_available,ks_modify;
static void do_generate_keypair( struct para_data_s *para,
struct output_control_s *outctrl );
struct output_control_s *outctrl, int card );
static int write_keyblock( IOBUF out, KBNODE node );
#ifdef ENABLE_CARD_SUPPORT
static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
u32 expireval, struct para_data_s *para);
#endif
static void
write_uid( KBNODE root, const char *s )
@ -1762,7 +1768,7 @@ get_parameter_revkey( struct para_data_s *para, enum para_name key )
static int
proc_parameter_file( struct para_data_s *para, const char *fname,
struct output_control_s *outctrl )
struct output_control_s *outctrl, int card )
{
struct para_data_s *r;
const char *s1, *s2, *s3;
@ -1874,7 +1880,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
return -1;
}
do_generate_keypair( para, outctrl );
do_generate_keypair( para, outctrl, card );
return 0;
}
@ -1958,7 +1964,7 @@ read_parameter_file( const char *fname )
outctrl.dryrun = 1;
else if( !ascii_strcasecmp( keyword, "%commit" ) ) {
outctrl.lnr = lnr;
proc_parameter_file( para, fname, &outctrl );
proc_parameter_file( para, fname, &outctrl, 0 );
release_parameter_list( para );
para = NULL;
}
@ -2018,7 +2024,7 @@ read_parameter_file( const char *fname )
if( keywords[i].key == pKEYTYPE && para ) {
outctrl.lnr = lnr;
proc_parameter_file( para, fname, &outctrl );
proc_parameter_file( para, fname, &outctrl, 0 );
release_parameter_list( para );
para = NULL;
}
@ -2046,7 +2052,7 @@ read_parameter_file( const char *fname )
}
else if( para ) {
outctrl.lnr = lnr;
proc_parameter_file( para, fname, &outctrl );
proc_parameter_file( para, fname, &outctrl, 0 );
}
if( outctrl.use_files ) { /* close open streams */
@ -2064,91 +2070,146 @@ read_parameter_file( const char *fname )
}
/****************
* Generate a keypair
* (fname is only used in batch mode)
/*
* 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.
*/
void
generate_keypair( const char *fname )
generate_keypair( const char *fname, const char *card_serialno )
{
unsigned int nbits;
char *uid = NULL;
DEK *dek;
STRING2KEY *s2k;
int algo;
unsigned int use;
int both = 0;
u32 expire;
struct para_data_s *para = NULL;
struct para_data_s *r;
struct output_control_s outctrl;
memset( &outctrl, 0, sizeof( outctrl ) );
if( opt.batch ) {
read_parameter_file( fname );
return;
unsigned int nbits;
char *uid = NULL;
DEK *dek;
STRING2KEY *s2k;
int algo;
unsigned int use;
int both = 0;
u32 expire;
struct para_data_s *para = NULL;
struct para_data_s *r;
struct output_control_s outctrl;
memset( &outctrl, 0, sizeof( outctrl ) );
if (opt.batch && card_serialno)
{
/* We don't yet support unattended key generation. */
log_error (_("sorry, can't do this in batch mode\n"));
return;
}
if (opt.batch)
{
read_parameter_file( fname );
return;
}
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;
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;
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 = 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;
#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;
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;
}
}
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;
}
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;
}
}
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);
expire = ask_expire_interval(0);
r = m_alloc_clear( sizeof *r + 20 );
r->key = pKEYEXPIRE;
r->u.expire = expire;
@ -2161,19 +2222,21 @@ generate_keypair( const char *fname )
para = r;
uid = ask_user_id(0);
if( !uid ) {
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 = do_ask_passphrase( &s2k );
if( dek ) {
dek = card_serialno? NULL : do_ask_passphrase( &s2k );
if( dek )
{
r = m_alloc_clear( sizeof *r );
r->key = pPASSPHRASE_DEK;
r->u.dek = dek;
@ -2184,9 +2247,9 @@ generate_keypair( const char *fname )
r->u.s2k = s2k;
r->next = para;
para = r;
}
proc_parameter_file( para, "[internal]", &outctrl );
}
proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno);
release_parameter_list( para );
}
@ -2211,7 +2274,7 @@ print_status_key_created (int letter, PKT_public_key *pk)
static void
do_generate_keypair( struct para_data_s *para,
struct output_control_s *outctrl )
struct output_control_s *outctrl, int card )
{
KBNODE pub_root = NULL;
KBNODE sec_root = NULL;
@ -2270,7 +2333,11 @@ do_generate_keypair( struct para_data_s *para,
assert( outctrl->sec.stream );
if( opt.verbose ) {
log_info(_("writing public key to `%s'\n"), outctrl->pub.fname );
log_info(_("writing secret key to `%s'\n"), outctrl->sec.fname );
if (card)
log_info (_("writing secret key stub to `%s'\n"),
outctrl->sec.fname);
else
log_info(_("writing secret key to `%s'\n"), outctrl->sec.fname );
}
}
@ -2283,13 +2350,26 @@ do_generate_keypair( struct para_data_s *para,
pub_root = make_comment_node("#"); delete_kbnode(pub_root);
sec_root = make_comment_node("#"); delete_kbnode(sec_root);
rc = do_create( get_parameter_algo( para, pKEYTYPE ),
get_parameter_uint( para, pKEYLENGTH ),
pub_root, sec_root,
get_parameter_dek( para, pPASSPHRASE_DEK ),
get_parameter_s2k( para, pPASSPHRASE_S2K ),
&sk,
get_parameter_u32( para, pKEYEXPIRE ) );
if (!card)
{
rc = do_create( get_parameter_algo( para, pKEYTYPE ),
get_parameter_uint( para, pKEYLENGTH ),
pub_root, sec_root,
get_parameter_dek( para, pPASSPHRASE_DEK ),
get_parameter_s2k( para, pPASSPHRASE_S2K ),
&sk,
get_parameter_u32( para, pKEYEXPIRE ) );
}
else
{
rc = gen_card_key (PUBKEY_ALGO_RSA, 1, pub_root, sec_root,
get_parameter_u32 (para, pKEYEXPIRE), para);
if (!rc)
{
sk = sec_root->next->pkt->pkt.secret_key;
assert (sk);
}
}
if(!rc && (revkey=get_parameter_revkey(para,pREVOKER)))
{
@ -2310,24 +2390,44 @@ do_generate_keypair( struct para_data_s *para,
get_parameter_uint (para, pKEYUSAGE));
}
if( get_parameter( para, pSUBKEYTYPE ) ) {
rc = do_create( get_parameter_algo( para, pSUBKEYTYPE ),
get_parameter_uint( para, pSUBKEYLENGTH ),
pub_root, sec_root,
get_parameter_dek( para, pPASSPHRASE_DEK ),
get_parameter_s2k( para, pPASSPHRASE_S2K ),
NULL,
get_parameter_u32( para, pSUBKEYEXPIRE ) );
if( !rc )
rc = write_keybinding(pub_root, pub_root, sk,
get_parameter_uint (para, pSUBKEYUSAGE));
if( !rc )
rc = write_keybinding(sec_root, pub_root, sk,
get_parameter_uint (para, pSUBKEYUSAGE));
if( get_parameter( para, pSUBKEYTYPE ) )
{
if (!card)
{
rc = do_create( get_parameter_algo( para, pSUBKEYTYPE ),
get_parameter_uint( para, pSUBKEYLENGTH ),
pub_root, sec_root,
get_parameter_dek( para, pPASSPHRASE_DEK ),
get_parameter_s2k( para, pPASSPHRASE_S2K ),
NULL,
get_parameter_u32( para, pSUBKEYEXPIRE ) );
}
else
{
rc = gen_card_key (PUBKEY_ALGO_RSA, 2, pub_root, sec_root,
get_parameter_u32 (para, pKEYEXPIRE), para);
}
if( !rc )
rc = write_keybinding(pub_root, pub_root, sk,
get_parameter_uint (para, pSUBKEYUSAGE));
if( !rc )
rc = write_keybinding(sec_root, pub_root, sk,
get_parameter_uint (para, pSUBKEYUSAGE));
did_sub = 1;
}
}
if (card && get_parameter (para, pAUTHKEYTYPE))
{
rc = gen_card_key (PUBKEY_ALGO_RSA, 3, pub_root, sec_root,
get_parameter_u32 (para, pKEYEXPIRE), para);
if (!rc)
rc = write_keybinding (pub_root, pub_root, sk, PUBKEY_USAGE_AUTH);
if (!rc)
rc = write_keybinding (sec_root, pub_root, sk, PUBKEY_USAGE_AUTH);
}
if( !rc && outctrl->use_files ) { /* direct write to specified files */
rc = write_keyblock( outctrl->pub.stream, pub_root );
if( rc )
@ -2359,8 +2459,12 @@ do_generate_keypair( struct para_data_s *para,
if (!rc && opt.verbose) {
log_info(_("writing public key to `%s'\n"),
keydb_get_resource_name (pub_hd));
log_info(_("writing secret key to `%s'\n"),
keydb_get_resource_name (sec_hd));
if (card)
log_info (_("writing secret key stub to `%s'\n"),
keydb_get_resource_name (sec_hd));
else
log_info(_("writing secret key to `%s'\n"),
keydb_get_resource_name (sec_hd));
}
if (!rc) {
@ -2426,8 +2530,8 @@ do_generate_keypair( struct para_data_s *para,
}
release_kbnode( pub_root );
release_kbnode( sec_root );
if( sk ) /* the unprotected secret key */
free_secret_key(sk);
if( sk && !card) /* the unprotected secret key unless we have a */
free_secret_key(sk); /* shallow copy in card mode. */
}
@ -2554,3 +2658,81 @@ write_keyblock( IOBUF out, KBNODE node )
}
return 0;
}
static int
gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
u32 expireval, struct para_data_s *para)
{
#ifdef ENABLE_CARD_SUPPORT
int rc;
const char *s;
struct agent_card_genkey_s info;
PACKET *pkt;
PKT_secret_key *sk;
PKT_public_key *pk;
assert (algo == PUBKEY_ALGO_RSA);
rc = agent_scd_genkey (&info, keyno, 1);
/* if (gpg_err_code (rc) == GPG_ERR_EEXIST) */
/* { */
/* tty_printf ("\n"); */
/* log_error ("WARNING: key does already exists!\n"); */
/* tty_printf ("\n"); */
/* if ( cpr_get_answer_is_yes( "keygen.card.replace_key", */
/* _("Replace existing key? "))) */
/* rc = agent_scd_genkey (&info, keyno, 1); */
/* } */
if (rc)
{
log_error ("key generation failed: %s\n", gpg_strerror (rc));
return rc;
}
if ( !info.n || !info.e )
{
log_error ("communication error with SCD\n");
mpi_free (info.n);
mpi_free (info.e);
return gpg_error (GPG_ERR_GENERAL);
}
pk = xcalloc (1, sizeof *pk );
sk = xcalloc (1, sizeof *sk );
sk->timestamp = pk->timestamp = info.created_at;
sk->version = pk->version = 4;
if (expireval)
sk->expiredate = pk->expiredate = pk->timestamp + expireval;
sk->pubkey_algo = pk->pubkey_algo = algo;
pk->pkey[0] = info.n;
pk->pkey[1] = info.e;
sk->skey[0] = mpi_copy (pk->pkey[0]);
sk->skey[1] = mpi_copy (pk->pkey[1]);
sk->skey[2] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10);
sk->is_protected = 1;
sk->protect.s2k.mode = 1002;
s = get_parameter_value (para, pSERIALNO);
if (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);
}
pkt = xcalloc (1,sizeof *pkt);
pkt->pkttype = keyno == 1 ? 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 = keyno == 1 ? 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*/
}

View File

@ -143,7 +143,7 @@ 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 );
void generate_keypair( const char *fname, const char *card_serialno );
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 );
@ -241,4 +241,11 @@ void pause_on_sigusr( int which );
void block_all_signals(void);
void unblock_all_signals(void);
#ifdef ENABLE_CARD_SUPPORT
/*-- card-util.c --*/
void change_pin (int no);
void card_status (FILE *fp);
void card_edit (STRLIST commands);
#endif
#endif /*G10_MAIN_H*/

View File

@ -309,7 +309,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
#ifdef ENABLE_CARD_SUPPORT
if (sk->is_protected && sk->protect.s2k.mode == 1002)
{
char *rbuf;
unsigned char *rbuf;
size_t rbuflen;
char *snbuf;