aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shaw <[email protected]>2002-05-16 03:35:55 +0000
committerDavid Shaw <[email protected]>2002-05-16 03:35:55 +0000
commit4dcdaa3b1b05bd632c122c16839181ba9a039a5c (patch)
tree14c9054017b17eea9570aea8e479f054041d0b14
parent* options.skel: keyserver.pgp.com is gone, so list pgp.surfnet.nl as a (diff)
downloadgnupg-4dcdaa3b1b05bd632c122c16839181ba9a039a5c.tar.gz
gnupg-4dcdaa3b1b05bd632c122c16839181ba9a039a5c.zip
* main.h, keygen.c (keygen_add_revkey): Add revocation key subpackets to a
signature (callable by make_keysig_packet). (write_direct_sig): Write a 1F direct key signature. (parse_revocation_key): Parse a string in algo:fpr:sensitive format into a revocation key. (get_parameter_revkey, do_generate_keypair): Call above functions when prompted from a batch key generation file. * build-packet.c (build_sig_subpkt): Allow multiple revocation key subpackets in a single sig. * keydb.h, getkey.c (get_seckey_byfprint): Same as get_pubkey_byfprint, except for secret keys. We only know the fingerprint of a revocation key, so this is needed to retrieve the secret key needed to issue a revokation. * packet.h, parse-packet.c (parse_signature, parse_revkeys): Split revkey parsing off into a new function that can be used to reparse after manipulating the revkey list. * sign.c (make_keysig_packet): Ability to make 1F direct key signatures.
-rw-r--r--g10/ChangeLog25
-rw-r--r--g10/build-packet.c1
-rw-r--r--g10/getkey.c35
-rw-r--r--g10/keydb.h2
-rw-r--r--g10/keygen.c140
-rw-r--r--g10/main.h1
-rw-r--r--g10/packet.h1
-rw-r--r--g10/parse-packet.c48
-rw-r--r--g10/sign.c6
9 files changed, 232 insertions, 27 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 8660d5853..13208048d 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,28 @@
+2002-05-16 David Shaw <[email protected]>
+
+ * main.h, keygen.c (keygen_add_revkey): Add revocation key
+ subpackets to a signature (callable by
+ make_keysig_packet). (write_direct_sig): Write a 1F direct key
+ signature. (parse_revocation_key): Parse a string in
+ algo:fpr:sensitive format into a revocation
+ key. (get_parameter_revkey, do_generate_keypair): Call above
+ functions when prompted from a batch key generation file.
+
+ * build-packet.c (build_sig_subpkt): Allow multiple revocation key
+ subpackets in a single sig.
+
+ * keydb.h, getkey.c (get_seckey_byfprint): Same as
+ get_pubkey_byfprint, except for secret keys. We only know the
+ fingerprint of a revocation key, so this is needed to retrieve the
+ secret key needed to issue a revokation.
+
+ * packet.h, parse-packet.c (parse_signature, parse_revkeys): Split
+ revkey parsing off into a new function that can be used to reparse
+ after manipulating the revkey list.
+
+ * sign.c (make_keysig_packet): Ability to make 1F direct key
+ signatures.
+
2002-05-15 David Shaw <[email protected]>
* options.skel: keyserver.pgp.com is gone, so list pgp.surfnet.nl
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 1efb4895f..0a4d97d8a 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -710,6 +710,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
{
case SIGSUBPKT_NOTATION:
case SIGSUBPKT_POLICY:
+ case SIGSUBPKT_REV_KEY:
/* we do allow multiple subpackets */
break;
diff --git a/g10/getkey.c b/g10/getkey.c
index a11d1b94b..88f01f9ba 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -963,6 +963,41 @@ get_seckey_end( GETKEY_CTX ctx )
}
+/****************
+ * Search for a key with the given fingerprint.
+ * FIXME:
+ * We should replace this with the _byname function. Thiscsan be done
+ * by creating a userID conforming to the unified fingerprint style.
+ */
+int
+get_seckey_byfprint( PKT_secret_key *sk,
+ const byte *fprint, size_t fprint_len)
+{
+ int rc;
+
+ if( fprint_len == 20 || fprint_len == 16 ) {
+ struct getkey_ctx_s ctx;
+ KBNODE kb = NULL;
+
+ memset( &ctx, 0, sizeof ctx );
+ ctx.exact = 1 ;
+ ctx.not_allocated = 1;
+ ctx.kr_handle = keydb_new (1);
+ ctx.nitems = 1;
+ ctx.items[0].mode = fprint_len==16? KEYDB_SEARCH_MODE_FPR16
+ : KEYDB_SEARCH_MODE_FPR20;
+ memcpy( ctx.items[0].u.fpr, fprint, fprint_len );
+ rc = lookup( &ctx, &kb, 1 );
+ if (!rc && sk )
+ sk_from_block ( &ctx, sk, kb );
+ release_kbnode ( kb );
+ get_pubkey_end( &ctx );
+ }
+ else
+ rc = G10ERR_GENERAL; /* Oops */
+ return rc;
+}
+
/************************************************
************* Merging stuff ********************
diff --git a/g10/keydb.h b/g10/keydb.h
index 8432c93d2..620772c34 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -206,6 +206,8 @@ int seckey_available( u32 *keyid );
int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock );
int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk,
STRLIST names, KBNODE *ret_keyblock );
+int get_seckey_byfprint( PKT_secret_key *sk,
+ const byte *fprint, size_t fprint_len);
int get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock );
void get_seckey_end( GETKEY_CTX ctx );
int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys );
diff --git a/g10/keygen.c b/g10/keygen.c
index d5b647314..b8c95d942 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -50,6 +50,7 @@ enum para_name {
pNAMEEMAIL,
pNAMECOMMENT,
pPREFERENCES,
+ pREVOKER,
pUSERID,
pEXPIREDATE,
pKEYEXPIRE, /* in n seconds */
@@ -67,7 +68,8 @@ struct para_data_s {
DEK *dek;
STRING2KEY *s2k;
u32 expire;
- unsigned int usage;
+ unsigned int usage;
+ struct revocation_key revkey;
char value[1];
} u;
};
@@ -383,6 +385,68 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque )
return 0;
}
+int
+keygen_add_revkey(PKT_signature *sig, void *opaque)
+{
+ struct revocation_key *revkey=opaque;
+ byte buf[2+MAX_FINGERPRINT_LEN];
+
+ buf[0]=revkey->class;
+ buf[1]=revkey->algid;
+ memcpy(&buf[2],revkey->fpr,MAX_FINGERPRINT_LEN);
+
+ build_sig_subpkt(sig,SIGSUBPKT_REV_KEY,buf,2+MAX_FINGERPRINT_LEN);
+
+ sig->revkey=m_realloc(sig->revkey,
+ sizeof(struct revocation_key *)*(sig->numrevkeys+1));
+
+ /* All sigs with revocation keys set are nonrevocable */
+ sig->flags.revocable=0;
+ buf[0] = 0;
+ build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 );
+
+ parse_revkeys(sig);
+
+ return 0;
+}
+
+static int
+write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk,
+ struct revocation_key *revkey )
+{
+ PACKET *pkt;
+ PKT_signature *sig;
+ int rc=0;
+ KBNODE node;
+ PKT_public_key *pk;
+
+ if( opt.verbose )
+ log_info(_("writing direct signature\n"));
+
+ /* get the pk packet from the pub_tree */
+ node = find_kbnode( pub_root, PKT_PUBLIC_KEY );
+ if( !node )
+ BUG();
+ pk = node->pkt->pkt.public_key;
+
+ /* we have to cache the key, so that the verification of the signature
+ * creation is able to retrieve the public key */
+ cache_public_key (pk);
+
+ /* and make the signature */
+ rc = make_keysig_packet(&sig,pk,NULL,NULL,sk,0x1F,0,0,0,0,
+ keygen_add_revkey,revkey);
+ if( rc ) {
+ log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
+ return rc;
+ }
+
+ pkt = m_alloc_clear( sizeof *pkt );
+ pkt->pkttype = PKT_SIGNATURE;
+ pkt->pkt.signature = sig;
+ add_kbnode( root, new_kbnode( pkt ) );
+ return rc;
+}
static int
write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk,
@@ -1385,6 +1449,59 @@ parse_parameter_usage (const char *fname,
return 0;
}
+static int
+parse_revocation_key (const char *fname,
+ struct para_data_s *para, enum para_name key)
+{
+ struct para_data_s *r = get_parameter( para, key );
+ struct revocation_key revkey;
+ char *pn;
+ int i;
+
+ if( !r )
+ return 0; /* none (this is an optional parameter) */
+
+ pn = r->u.value;
+
+ revkey.class=0x80;
+ revkey.algid=atoi(pn);
+ if(!revkey.algid)
+ goto fail;
+
+ /* Skip to the fpr */
+ while(*pn && *pn!=':')
+ pn++;
+
+ if(*pn!=':')
+ goto fail;
+
+ pn++;
+
+ for(i=0;i<MAX_FINGERPRINT_LEN && *pn;i++,pn+=2)
+ {
+ int c=hextobyte(pn);
+ if(c==-1)
+ goto fail;
+
+ revkey.fpr[i]=c;
+ }
+
+ /* skip to the tag */
+ while(*pn && *pn!='s' && *pn!='S')
+ pn++;
+
+ if(ascii_strcasecmp(pn,"sensitive")==0)
+ revkey.class|=0x40;
+
+ memcpy(&r->u.revkey,&revkey,sizeof(struct revocation_key));
+
+ return 0;
+
+ fail:
+ log_error("%s:%d: invalid revocation key\n", fname, r->lnr );
+ return -1; /* error */
+}
+
static u32
get_parameter_u32( struct para_data_s *para, enum para_name key )
@@ -1421,6 +1538,12 @@ get_parameter_s2k( struct para_data_s *para, enum para_name key )
return r? r->u.s2k : NULL;
}
+static struct revocation_key *
+get_parameter_revkey( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+ return r? &r->u.revkey : NULL;
+}
static int
proc_parameter_file( struct para_data_s *para, const char *fname,
@@ -1478,6 +1601,10 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
/* Set preferences, if any. */
keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ));
+ /* Set revoker, if any. */
+ if (parse_revocation_key (fname, para, pREVOKER))
+ return -1;
+
/* make DEK and S2K from the Passphrase */
r = get_parameter( para, pPASSPHRASE );
if( r && *r->u.value ) {
@@ -1559,6 +1686,7 @@ read_parameter_file( const char *fname )
{ "Expire-Date", pEXPIREDATE },
{ "Passphrase", pPASSPHRASE },
{ "Preferences", pPREFERENCES },
+ { "Revoker", pREVOKER },
{ NULL, 0 }
};
FILE *fp;
@@ -1845,6 +1973,7 @@ do_generate_keypair( struct para_data_s *para,
KBNODE sec_root = NULL;
PKT_secret_key *sk = NULL;
const char *s;
+ struct revocation_key *revkey;
int rc;
int did_sub = 0;
@@ -1917,6 +2046,14 @@ do_generate_keypair( struct para_data_s *para,
get_parameter_s2k( para, pPASSPHRASE_S2K ),
&sk,
get_parameter_u32( para, pKEYEXPIRE ) );
+
+ if(!rc && (revkey=get_parameter_revkey(para,pREVOKER)))
+ {
+ rc=write_direct_sig(pub_root,pub_root,sk,revkey);
+ if(!rc)
+ write_direct_sig(sec_root,pub_root,sk,revkey);
+ }
+
if( !rc && (s=get_parameter_value(para, pUSERID)) ) {
write_uid(pub_root, s );
if( !rc )
@@ -2170,4 +2307,3 @@ write_keyblock( IOBUF out, KBNODE node )
}
return 0;
}
-
diff --git a/g10/main.h b/g10/main.h
index cba4d4d73..6400a5f99 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -117,6 +117,7 @@ char *keygen_get_std_prefs (void);
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
int keygen_upd_std_prefs( PKT_signature *sig, void *opaque );
+int keygen_add_revkey(PKT_signature *sig, void *opaque);
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
/*-- openfile.c --*/
diff --git a/g10/packet.h b/g10/packet.h
index d4f022a7a..01d32db87 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -394,6 +394,7 @@ const byte *parse_sig_subpkt ( const subpktarea_t *buffer,
const byte *parse_sig_subpkt2 ( PKT_signature *sig,
sigsubpkttype_t reqtype,
size_t *ret_n );
+void parse_revkeys(PKT_signature *sig);
int parse_attribute_subpkts(PKT_user_id *uid);
void make_attribute_uidname(PKT_user_id *uid);
PACKET *create_gpg_control ( ctrlpkttype_t type,
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 7f0d8fe0d..df42e6282 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -1121,6 +1121,31 @@ parse_sig_subpkt2 (PKT_signature *sig, sigsubpkttype_t reqtype,
return p;
}
+/* Find all revocation keys. Look in hashed area only. */
+void parse_revkeys(PKT_signature *sig)
+{
+ struct revocation_key *revkey;
+ int seq=0;
+ size_t len;
+
+ if(sig->sig_class!=0x1F)
+ return;
+
+ while((revkey=
+ (struct revocation_key *)enum_sig_subpkt(sig->hashed,
+ SIGSUBPKT_REV_KEY,
+ &len,&seq)))
+ {
+ if(len==sizeof(struct revocation_key) &&
+ (revkey->class&0x80)) /* 0x80 bit must be set */
+ {
+ sig->revkey=m_realloc(sig->revkey,
+ sizeof(struct revocation_key *)*(sig->numrevkeys+1));
+ sig->revkey[sig->numrevkeys]=revkey;
+ sig->numrevkeys++;
+ }
+ }
+}
static int
parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
@@ -1261,28 +1286,9 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
if(p && *p==0)
sig->flags.exportable=0;
- /* Find all revocation keys. Back to hashed area only. */
+ /* Find all revocation keys. */
if(sig->sig_class==0x1F)
- {
- struct revocation_key *revkey;
- int seq=0;
- size_t len;
-
- while((revkey=
- (struct revocation_key *)enum_sig_subpkt(sig->hashed,
- SIGSUBPKT_REV_KEY,
- &len,&seq)))
- {
- if(len==sizeof(struct revocation_key) &&
- (revkey->class&0x80)) /* 0x80 bit must be set */
- {
- sig->revkey=m_realloc(sig->revkey,
- sizeof(struct revocation_key *)*(sig->numrevkeys+1));
- sig->revkey[sig->numrevkeys]=revkey;
- sig->numrevkeys++;
- }
- }
- }
+ parse_revkeys(sig);
}
if( list_mode ) {
diff --git a/g10/sign.c b/g10/sign.c
index 59e517898..fe6e62312 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -1097,7 +1097,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
int rc=0;
MD_HANDLE md;
- assert( (sigclass >= 0x10 && sigclass <= 0x13)
+ assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F
|| sigclass == 0x20 || sigclass == 0x18
|| sigclass == 0x30 || sigclass == 0x28 );
@@ -1140,7 +1140,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
if( sigclass == 0x18 || sigclass == 0x28 ) { /* subkey binding/revocation*/
hash_public_key( md, subpk );
}
- else if( sigclass != 0x20 ) {
+ else if( sigclass != 0x1F && sigclass != 0x20 ) {
hash_uid (md, sigversion, uid);
}
/* and make the signature packet */
@@ -1241,5 +1241,3 @@ update_keysig_packet( PKT_signature **ret_sig,
*ret_sig = sig;
return rc;
}
-
-