aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2003-09-30 08:00:08 +0000
committerWerner Koch <[email protected]>2003-09-30 08:00:08 +0000
commit8062cb418a4757c603447fb5fad2d06bf54cadb3 (patch)
treec4290b18aed7add7b1355acd16b5d0876edc8ac3
parent2003-09-28 Timo Schulz <[email protected]> (diff)
downloadgnupg-8062cb418a4757c603447fb5fad2d06bf54cadb3.tar.gz
gnupg-8062cb418a4757c603447fb5fad2d06bf54cadb3.zip
* keygen.c (do_add_key_flags, parse_parameter_usage): Add support
the proposed AUTH key flag. * getkey.c (fixup_uidnode, merge_selfsigs_main) (merge_selfsigs_subkey, premerge_public_with_secret): Ditto. * keylist.c (print_capabilities): Ditto. * parse-packet.c (parse_key): Allow to parse the divert-to-card S2K mode. * build-packet.c (do_secret_key): Handle divert-to-card S2K * seckey-cert.c (is_secret_key_protected): Ditto. (check_secret_key): Ditto. * keygen.c (do_ask_passphrase): Renamed from ask_passphrase. * passphrase.c (ask_passphrase): New.
Diffstat (limited to '')
-rw-r--r--g10/ChangeLog17
-rw-r--r--g10/build-packet.c13
-rw-r--r--g10/cardglue.c50
-rw-r--r--g10/getkey.c9
-rw-r--r--g10/keydb.h2
-rw-r--r--g10/keygen.c8
-rw-r--r--g10/keylist.c11
-rw-r--r--g10/parse-packet.c24
-rw-r--r--g10/passphrase.c65
-rw-r--r--g10/seckey-cert.c8
-rw-r--r--g10/sign.c19
-rw-r--r--include/ChangeLog4
-rw-r--r--include/cipher.h1
13 files changed, 193 insertions, 38 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index a0905eda4..7b0448de4 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,20 @@
+2003-09-29 Werner Koch <[email protected]>
+
+ * keygen.c (do_add_key_flags, parse_parameter_usage): Add support
+ the proposed AUTH key flag.
+ * getkey.c (fixup_uidnode, merge_selfsigs_main)
+ (merge_selfsigs_subkey, premerge_public_with_secret): Ditto.
+ * keylist.c (print_capabilities): Ditto.
+
+ * parse-packet.c (parse_key): Allow to parse the divert-to-card
+ S2K mode.
+ * build-packet.c (do_secret_key): Handle divert-to-card S2K
+ * seckey-cert.c (is_secret_key_protected): Ditto.
+ (check_secret_key): Ditto.
+
+ * keygen.c (do_ask_passphrase): Renamed from ask_passphrase.
+ * passphrase.c (ask_passphrase): New.
+
2003-09-28 Werner Koch <[email protected]>
* g10.c (main): New commands --card-edit, --card-status and
diff --git a/g10/build-packet.c b/g10/build-packet.c
index af97be423..cd0bb8a81 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -410,8 +410,9 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
if( sk->protect.s2k.mode == 3 )
iobuf_put(a, sk->protect.s2k.count );
- /* For out special mode 1001 we do not need an IV */
- if( sk->protect.s2k.mode != 1001 )
+ /* For out special modes 1001, 1002 we do not need an IV */
+ if( sk->protect.s2k.mode != 1001
+ && sk->protect.s2k.mode != 1002 )
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
}
}
@@ -420,6 +421,14 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
if( sk->protect.s2k.mode == 1001 )
; /* GnuPG extension - don't write a secret key at all */
+ else if( sk->protect.s2k.mode == 1002 )
+ { /* GnuPG extension - divert to OpenPGP smartcard. */
+ iobuf_put(a, sk->protect.ivlen ); /* length of the serial
+ number or 0 for no serial
+ number. */
+ /* The serial number gets stored in the IV field. */
+ iobuf_write(a, sk->protect.iv, sk->protect.ivlen);
+ }
else if( sk->is_protected && sk->version >= 4 ) {
/* The secret key is protected - write it out as it is */
byte *p;
diff --git a/g10/cardglue.c b/g10/cardglue.c
index 8924889dd..358eb90f6 100644
--- a/g10/cardglue.c
+++ b/g10/cardglue.c
@@ -53,7 +53,7 @@ struct ctrl_ctx_s {
static char *default_reader_port;
-
+static APP current_app;
@@ -246,6 +246,7 @@ open_card (void)
int rc;
APP app;
+ current_app = NULL;/* FIXME: Release it first.*/
slot = apdu_open_reader (default_reader_port);
if (slot == -1)
{
@@ -265,6 +266,7 @@ open_card (void)
}
app->initialized = 1;
+ current_app = app;
return app;
}
@@ -443,7 +445,7 @@ agent_learn (struct agent_card_info_s *info)
time_t stamp;
char *serial;
- app = open_card ();
+ app = current_app? current_app : open_card ();
if (!app)
return gpg_error (GPG_ERR_CARD);
@@ -462,13 +464,39 @@ agent_learn (struct agent_card_info_s *info)
return rc;
}
+static int
+pin_cb (void *opaque, const char *info, char **retstr)
+{
+ char *value;
+ int canceled;
+
+ *retstr = NULL;
+ log_debug ("asking for PIN '%s'\n", info);
+
+ value = ask_passphrase (info, "Enter PIN: ", &canceled);
+ if (!value && canceled)
+ return -1;
+ else if (!value)
+ return G10ERR_GENERAL;
+
+ *retstr = value;
+ return 0;
+}
+
+
+
/* Send a SETATTR command to the SCdaemon. */
int
agent_scd_setattr (const char *name,
const unsigned char *value, size_t valuelen)
{
+ APP app;
- return gpg_error (GPG_ERR_CARD);
+ app = current_app? current_app : open_card ();
+ if (!app)
+ return gpg_error (GPG_ERR_CARD);
+
+ return app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
}
/* Send a GENKEY command to the SCdaemon. */
@@ -481,12 +509,24 @@ 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,
+agent_scd_pksign (const char *serialno, int hashalgo,
const unsigned char *indata, size_t indatalen,
char **r_buf, size_t *r_buflen)
{
+ APP app;
- return gpg_error (GPG_ERR_CARD);
+ *r_buf = NULL;
+ *r_buflen = 0;
+ app = current_app? current_app : open_card ();
+ if (!app)
+ return gpg_error (GPG_ERR_CARD);
+
+ /* Check that the card's serialnumber is as required.*/
+
+ return app->fnc.sign (app, serialno, hashalgo,
+ pin_cb, NULL,
+ indata, indatalen,
+ r_buf, r_buflen);
}
diff --git a/g10/getkey.c b/g10/getkey.c
index 5e4ca44e2..72b80ba76 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1279,6 +1279,8 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
uid->help_key_usage |= PUBKEY_USAGE_ENC;
/* Note: we do not set the CERT flag here because it can be assumed
* that thre is no real policy to set it. */
+ if ( (*p & 0x20) )
+ uid->help_key_usage |= PUBKEY_USAGE_AUTH;
}
/* ditto or the key expiration */
@@ -1490,6 +1492,8 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked )
key_usage |= PUBKEY_USAGE_SIG;
if ( (*p & 12) )
key_usage |= PUBKEY_USAGE_ENC;
+ if ( (*p & 0x20) )
+ key_usage |= PUBKEY_USAGE_AUTH;
}
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
@@ -1878,6 +1882,8 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
key_usage |= PUBKEY_USAGE_SIG;
if ( (*p & 12) )
key_usage |= PUBKEY_USAGE_ENC;
+ if ( (*p & 0x20) )
+ key_usage |= PUBKEY_USAGE_AUTH;
}
if ( !key_usage ) { /* no key flags at all: get it from the algo */
key_usage = openpgp_pk_algo_usage ( subpk->pubkey_algo );
@@ -2075,7 +2081,8 @@ premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
/* The secret parts are not available so
we can't use that key for signing etc.
Fix the pubkey usage */
- pk->pubkey_usage &= ~PUBKEY_USAGE_SIG;
+ pk->pubkey_usage &= ~(PUBKEY_USAGE_SIG
+ |PUBKEY_USAGE_AUTH);
}
/* transfer flag bits 0 and 1 to the pubblock */
pub->flag |= (sec->flag &3);
diff --git a/g10/keydb.h b/g10/keydb.h
index 216add2e9..d02e427d8 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -186,6 +186,8 @@ int build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
int have_static_passphrase(void);
void read_passphrase_from_fd( int fd );
void passphrase_clear_cache ( u32 *keyid, int algo );
+char *ask_passphrase (const char *description, const char *prompt,
+ int *canceled);
DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text, int *canceled);
diff --git a/g10/keygen.c b/g10/keygen.c
index 4b736e16d..bcfdcfa67 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -145,6 +145,8 @@ do_add_key_flags (PKT_signature *sig, unsigned int use)
}
if (use & PUBKEY_USAGE_ENC)
buf[0] |= 0x04 | 0x08;
+ if (use & PUBKEY_USAGE_AUTH)
+ buf[0] |= 0x20;
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
}
@@ -1486,7 +1488,7 @@ ask_user_id( int mode )
static DEK *
-ask_passphrase( STRING2KEY **ret_s2k )
+do_ask_passphrase( STRING2KEY **ret_s2k )
{
DEK *dek = NULL;
STRING2KEY *s2k;
@@ -1651,6 +1653,8 @@ parse_parameter_usage (const char *fname,
use |= PUBKEY_USAGE_SIG;
else if ( !ascii_strcasecmp (p, "encrypt") )
use |= PUBKEY_USAGE_ENC;
+ else if ( !ascii_strcasecmp (p, "auth") )
+ use |= PUBKEY_USAGE_AUTH;
else {
log_error("%s:%d: invalid usage list\n", fname, r->lnr );
return -1; /* error */
@@ -2168,7 +2172,7 @@ generate_keypair( const char *fname )
r->next = para;
para = r;
- dek = ask_passphrase( &s2k );
+ dek = do_ask_passphrase( &s2k );
if( dek ) {
r = m_alloc_clear( sizeof *r );
r->key = pPASSPHRASE_DEK;
diff --git a/g10/keylist.c b/g10/keylist.c
index 262888102..de5b57572 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -475,11 +475,14 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock)
if( pk? pk->is_primary : sk->is_primary )
putchar ('c');
}
+
+ if ( (use & PUBKEY_USAGE_AUTH) )
+ putchar ('a');
}
if ( keyblock ) { /* figure out the usable capabilities */
KBNODE k;
- int enc=0, sign=0, cert=0, disabled=0;
+ int enc=0, sign=0, cert=0, auth=0, disabled=0;
for (k=keyblock; k; k = k->next ) {
if ( k->pkt->pkttype == PKT_PUBLIC_KEY
@@ -498,6 +501,8 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock)
if(pk->is_primary)
cert = 1;
}
+ if ( (pk->pubkey_usage & PUBKEY_USAGE_AUTH) )
+ auth = 1;
}
}
else if ( k->pkt->pkttype == PKT_SECRET_KEY
@@ -513,6 +518,8 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock)
if(sk->is_primary)
cert = 1;
}
+ if ( (sk->pubkey_usage & PUBKEY_USAGE_AUTH) )
+ auth = 1;
}
}
}
@@ -522,6 +529,8 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock)
putchar ('S');
if (cert)
putchar ('C');
+ if (auth)
+ putchar ('A');
if (disabled)
putchar ('D');
}
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 0831d26f4..e84609e47 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -1590,6 +1590,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *sk = pkt->pkt.secret_key;
byte temp[16];
+ size_t snlen = 0;
if( !npkey ) {
sk->skey[0] = mpi_set_opaque( NULL,
@@ -1662,6 +1663,8 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
break;
case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" );
break;
+ case 1002: if (list_mode) printf("\tgnu-divert-to-card S2K");
+ break;
default:
if( list_mode )
printf( "\tunknown %sS2K %d\n",
@@ -1697,6 +1700,19 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
printf("\tprotect count: %lu\n",
(ulong)sk->protect.s2k.count);
}
+ else if( sk->protect.s2k.mode == 1002 ) {
+ /* Read the serial number. */
+ if (pktlen < 1) {
+ rc = G10ERR_INVALID_PACKET;
+ goto leave;
+ }
+ snlen = iobuf_get (inp);
+ pktlen--;
+ if (pktlen < snlen || snlen == -1) {
+ rc = G10ERR_INVALID_PACKET;
+ goto leave;
+ }
+ }
}
/* Note that a sk->protect.algo > 110 is illegal, but I'm
not erroring on it here as otherwise there would be no
@@ -1726,6 +1742,8 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
}
if( sk->protect.s2k.mode == 1001 )
sk->protect.ivlen = 0;
+ else if( sk->protect.s2k.mode == 1002 )
+ sk->protect.ivlen = snlen < 16? snlen : 16;
if( pktlen < sk->protect.ivlen ) {
rc = G10ERR_INVALID_PACKET;
@@ -1734,7 +1752,8 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- )
temp[i] = iobuf_get_noeof(inp);
if( list_mode ) {
- printf( "\tprotect IV: ");
+ printf( sk->protect.s2k.mode == 1002? "\tserial-number: "
+ : "\tprotect IV: ");
for(i=0; i < sk->protect.ivlen; i++ )
printf(" %02x", temp[i] );
putchar('\n');
@@ -1747,7 +1766,8 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
* If the user is so careless, not to protect his secret key,
* we can assume, that he operates an open system :=(.
* So we put the key into secure memory when we unprotect it. */
- if( sk->protect.s2k.mode == 1001 ) {
+ if( sk->protect.s2k.mode == 1001
+ || sk->protect.s2k.mode == 1002 ) {
/* better set some dummy stuff here */
sk->skey[npkey] = mpi_set_opaque(NULL, m_strdup("dummydata"), 10);
pktlen = 0;
diff --git a/g10/passphrase.c b/g10/passphrase.c
index a48f220a2..10dd3ff81 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -1004,22 +1004,57 @@ passphrase_clear_cache ( u32 *keyid, int algo )
/****************
- * Get a passphrase for the secret key with KEYID, display TEXT
- * if the user needs to enter the passphrase.
- * mode 0 = standard, 1 = same but don't show key info,
- * 2 = create new passphrase
- * Returns: a DEK with a session key; caller must free
- * or NULL if the passphrase was not correctly repeated.
- * (only for mode 2)
- * a dek->keylen of 0 means: no passphrase entered.
- * (only for mode 2)
- *
- * pubkey_algo is only informational. Note that TRYAGAIN_TEXT must
- * not be translated as this is done within this function (required to
- * switch to utf-8 when the agent is in use). If CANCELED is not
- * NULL, it is set to 1 if the user choosed to cancel the operation,
- * otherwise it will be set to 0.
+ * Ask for a passphrase and return that string.
*/
+char *
+ask_passphrase (const char *description, const char *prompt, int *canceled)
+{
+ char *pw = NULL;
+
+ if (canceled)
+ *canceled = 0;
+
+ if (is_status_enabled())
+ write_status_text( STATUS_NEED_PASSPHRASE_SYM, "0 0 0");
+
+ if (!opt.batch && description)
+ tty_printf ("\n%s\n",description);
+
+ agent_died:
+ if ( opt.use_agent )
+ {
+ pw = agent_get_passphrase (NULL, 0, description, canceled );
+ if (!pw)
+ {
+ if (!opt.use_agent)
+ goto agent_died;
+ pw = NULL;
+ }
+ }
+ else if (fd_passwd)
+ {
+ pw = m_alloc_secure (strlen(fd_passwd)+1);
+ strcpy (pw, fd_passwd);
+ }
+ else if (opt.batch)
+ {
+ log_error(_("can't query password in batchmode\n"));
+ pw = NULL;
+ }
+ else {
+ pw = cpr_get_hidden("passphrase.ask",
+ prompt?prompt : _("Enter passphrase: ") );
+ tty_kill_prompt();
+ }
+
+ if (!pw || !*pw)
+ write_status( STATUS_MISSING_PASSPHRASE );
+
+ return pw;
+}
+
+
+
DEK *
passphrase_to_dek( u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index 76f0ee28d..5730735b8 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -225,6 +225,9 @@ check_secret_key( PKT_secret_key *sk, int n )
int rc = G10ERR_BAD_PASS;
int i,mode;
+ if (sk && sk->is_protected && sk->protect.s2k.mode == 1002)
+ return 0; /* Let the card support stuff handle this. */
+
if(n<0)
{
n=abs(n);
@@ -265,11 +268,14 @@ check_secret_key( PKT_secret_key *sk, int n )
/****************
* check whether the secret key is protected.
* Returns: 0 not protected, -1 on error or the protection algorithm
+ * -2 indicates a card stub.
*/
int
is_secret_key_protected( PKT_secret_key *sk )
{
- return sk->is_protected? sk->protect.algo : 0;
+ return sk->is_protected?
+ sk->protect.s2k.mode == 1002? -2
+ : sk->protect.algo : 0;
}
diff --git a/g10/sign.c b/g10/sign.c
index d1d981480..b7fd7bb20 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -313,18 +313,19 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
size_t rbuflen;
char *snbuf;
- snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen,sk);
- rc = G10ERR_GENERAL;
-/* agent_scd_pksign (snbuf, digest_algo, */
-/* gcry_md_read (md, digest_algo), */
-/* gcry_md_get_algo_dlen (digest_algo), */
-/* &rbuf, &rbuflen); */
+ snbuf = serialno_and_fpr_from_sk (sk->protect.iv,
+ sk->protect.ivlen, sk);
+ rc = agent_scd_pksign (snbuf, digest_algo,
+ md_read (md, digest_algo),
+ md_digest_length (digest_algo),
+ &rbuf, &rbuflen);
xfree (snbuf);
if (!rc)
{
-/* if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, */
-/* rbuf, rbuflen, NULL)) */
- BUG ();
+ sig->data[0] = mpi_alloc ( (rbuflen+BYTES_PER_MPI_LIMB-1)
+ / BYTES_PER_MPI_LIMB );
+ mpi_set_buffer (sig->data[0], rbuf, rbuflen, 0);
+ xfree (rbuf);
}
}
else
diff --git a/include/ChangeLog b/include/ChangeLog
index e9f720fe9..e0e1f35f0 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2003-09-29 Werner Koch <[email protected]>
+
+ * cipher.h (PUBKEY_USAGE_AUTH): New.
+
2003-09-28 Timo Schulz <[email protected]>
* util.h [WIN32]: Prototype for asprintf.
diff --git a/include/cipher.h b/include/cipher.h
index e450c1449..1a29c715c 100644
--- a/include/cipher.h
+++ b/include/cipher.h
@@ -54,6 +54,7 @@
#define PUBKEY_USAGE_SIG 1 /* key is good for signatures */
#define PUBKEY_USAGE_ENC 2 /* key is good for encryption */
#define PUBKEY_USAGE_CERT 4 /* key is also good to certify other keys*/
+#define PUBKEY_USAGE_AUTH 8 /* key is good for authentication */
#define DIGEST_ALGO_MD5 1
#define DIGEST_ALGO_SHA1 2