* keyedit.c (keyedit_menu, menu_backsign): New "backsign" command to
authorDavid Shaw <dshaw@jabberwocky.com>
Fri, 14 Oct 2005 04:07:13 +0000 (04:07 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Fri, 14 Oct 2005 04:07:13 +0000 (04:07 +0000)
add 0x19 backsigs to old keys that don't have them.

* misc.c (parse_options): Fix build warning.

* main.h, keygen.c (make_backsig): Make public.

g10/ChangeLog
g10/getkey.c
g10/keyedit.c
g10/keygen.c
g10/main.h
g10/misc.c

index e3fe1e2..aff9c6b 100644 (file)
@@ -1,3 +1,12 @@
+2005-10-13  David Shaw  <dshaw@jabberwocky.com>
+
+       * keyedit.c (keyedit_menu, menu_backsign): New "backsign" command
+       to add 0x19 backsigs to old keys that don't have them.
+
+       * misc.c (parse_options): Fix build warning.
+
+       * main.h, keygen.c (make_backsig): Make public.
+
 2005-10-12  David Shaw  <dshaw@jabberwocky.com>
 
        * options.h, getkey.c (merge_selfsigs_subkey), gpg.c (main),
index 241f153..2dde1bb 100644 (file)
@@ -2049,6 +2049,8 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
        int seq=0;
        size_t n;
 
+       /* We do this while() since there may be other embedded
+          signatures in the future.  We only want 0x19 here. */
        while((p=enum_sig_subpkt(sig->hashed,
                                 SIGSUBPKT_SIGNATURE,&n,&seq,NULL)))
          if(n>3 && ((p[0]==3 && p[2]==0x19) || (p[0]==4 && p[1]==0x19)))
@@ -2058,7 +2060,8 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
          {
            seq=0;
            /* It is safe to have this in the unhashed area since the
-              0x19 is located here for convenience, not security. */
+              0x19 is located on the selfsig for convenience, not
+              security. */
            while((p=enum_sig_subpkt(sig->unhashed,SIGSUBPKT_SIGNATURE,
                                     &n,&seq,NULL)))
              if(n>3 && ((p[0]==3 && p[2]==0x19) || (p[0]==4 && p[1]==0x19)))
index 346d0cb..55fc685 100644 (file)
@@ -63,6 +63,7 @@ static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_addrevoker( KBNODE pub_keyblock,
                            KBNODE sec_keyblock, int sensitive );
 static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
+static int menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock);
 static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_set_keyserver_url (const char *url,
@@ -1338,8 +1339,8 @@ enum cmdids
     cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
     cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
     cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
-    cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF,
-    cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST,
+    cmdEXPIRE, cmdBACKSIGN, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF,
+    cmdSETPREF, cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST,
     cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCLEAN, cmdNOP
   };
 
@@ -1363,6 +1364,7 @@ static struct
     { "key"     , cmdSELKEY    , 0, N_("select subkey N") },
     { "check"   , cmdCHECK     , 0, N_("check signatures") },
     { "c"       , cmdCHECK     , 0, NULL },
+    { "backsign", cmdBACKSIGN  , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
     { "sign"    , cmdSIGN      , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH,
       N_("sign selected user IDs [* see below for related commands]") },
     { "s"       , cmdSIGN      , KEYEDIT_NOT_SK, NULL },
@@ -2051,6 +2053,15 @@ keyedit_menu( const char *username, STRLIST locusr,
              }
            break;
 
+         case cmdBACKSIGN:
+           if(menu_backsign(keyblock,sec_keyblock))
+             {
+               sec_modified = 1;
+               modified = 1;
+               redisplay = 1;
+             }
+           break;
+
          case cmdPRIMARY:
            if( menu_set_primary_uid ( keyblock, sec_keyblock ) ) {
                merge_keys_and_selfsig( keyblock );
@@ -3623,6 +3634,151 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
 }
 
 static int
+menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock)
+{
+  int rc,modified=0;
+  PKT_public_key *main_pk;
+  PKT_secret_key *main_sk,*sub_sk=NULL;
+  KBNODE node;
+
+  assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
+  assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
+
+  merge_keys_and_selfsig(pub_keyblock);
+  main_pk=pub_keyblock->pkt->pkt.public_key;
+  main_sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
+  keyid_from_pk(main_pk,NULL);
+
+  for(node=pub_keyblock;node;node=node->next)
+    {
+      PKT_public_key *sub_pk=NULL;
+      KBNODE node2,sig_pk=NULL,sig_sk=NULL;
+      char *passphrase;
+
+      if(sub_sk)
+       {
+         free_secret_key(sub_sk);
+         sub_sk=NULL;
+       }
+
+      /* Find a signing subkey with no backsig */
+      if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY
+         && (node->pkt->pkt.public_key->pubkey_usage&PUBKEY_USAGE_SIG)
+         && !node->pkt->pkt.public_key->backsig)
+        sub_pk=node->pkt->pkt.public_key;
+
+      if(!sub_pk)
+       continue;
+
+      /* Find the selected selfsig on this subkey */
+      for(node2=node->next;
+         node2 && node2->pkt->pkttype==PKT_SIGNATURE;
+         node2=node2->next)
+       if(node2->pkt->pkt.signature->version>=4
+          && node2->pkt->pkt.signature->flags.chosen_selfsig)
+         {
+           sig_pk=node2;
+           break;
+         }
+
+      if(!sig_pk)
+       continue;
+
+      /* Find the secret subkey that matches the public subkey */
+      for(node2=sec_keyblock;node2;node2=node2->next)
+       if(node2->pkt->pkttype==PKT_SECRET_SUBKEY
+          && !cmp_public_secret_key(sub_pk,node2->pkt->pkt.secret_key))
+         {
+           sub_sk=copy_secret_key(NULL,node2->pkt->pkt.secret_key);
+           break;
+         }
+
+      if(!sub_sk)
+       continue;
+
+      /* Now finally find the matching selfsig on the secret subkey.
+        We can't use chosen_selfsig here (it's not set for secret
+        keys), so we just pick the selfsig with the right class.
+        This is what menu_expire does as well. */
+      for(node2=node2->next;
+         node2 && node2->pkt->pkttype==PKT_SIGNATURE;
+         node2=node2->next)
+       if(node2->pkt->pkt.signature->version>=4
+          && node2->pkt->pkt.signature->keyid[0]==sig_pk->pkt->pkt.signature->keyid[0]
+          && node2->pkt->pkt.signature->keyid[1]==sig_pk->pkt->pkt.signature->keyid[1]
+          && node2->pkt->pkt.signature->sig_class==sig_pk->pkt->pkt.signature->sig_class)
+         {
+           sig_sk=node2;
+           break;
+         }
+
+      if(!sig_sk)
+       continue;
+
+      /* Now we can get to work.  We have a main key and secret part,
+        a signing subkey with signature and secret part with
+        signature. */
+
+      passphrase=get_last_passphrase();
+      set_next_passphrase(passphrase);
+      xfree(passphrase);
+
+      rc=make_backsig(sig_pk->pkt->pkt.signature,main_pk,sub_pk,sub_sk);
+      if(rc==0)
+       {
+         PKT_signature *newsig;
+         PACKET *newpkt;
+
+         passphrase=get_last_passphrase();
+         set_next_passphrase(passphrase);
+         xfree(passphrase);
+
+         rc=update_keysig_packet(&newsig,sig_pk->pkt->pkt.signature,main_pk,
+                                 NULL,sub_pk,main_sk,NULL,NULL);
+         if(rc==0)
+           {
+             /* Put the new sig into place on the pubkey */
+             newpkt=xmalloc_clear(sizeof(*newpkt));
+             newpkt->pkttype=PKT_SIGNATURE;
+             newpkt->pkt.signature=newsig;
+             free_packet(sig_pk->pkt);
+             xfree(sig_pk->pkt);
+             sig_pk->pkt=newpkt;
+
+             /* Put the new sig into place on the seckey */
+             newpkt=xmalloc_clear(sizeof(*newpkt));
+             newpkt->pkttype=PKT_SIGNATURE;
+             newpkt->pkt.signature=copy_signature(NULL,newsig);
+             free_packet(sig_sk->pkt);
+             xfree(sig_sk->pkt);
+             sig_sk->pkt=newpkt;
+
+             modified=1;
+           }
+         else
+           {
+             log_error("update_keysig_packet failed: %s\n",g10_errstr(rc));
+             break;
+           }
+       }
+      else
+       {
+         log_error("make_backsig failed: %s\n",g10_errstr(rc));
+         break;
+       }
+    }
+
+  set_next_passphrase(NULL);
+
+  free_secret_key(main_sk);
+  if(sub_sk)
+    free_secret_key(sub_sk);
+
+  return modified;
+}
+
+
+static int
 change_primary_uid_cb ( PKT_signature *sig, void *opaque )
 {
     byte buf[1];
index 72df993..ae1ac63 100644 (file)
@@ -711,7 +711,7 @@ keygen_add_revkey(PKT_signature *sig, void *opaque)
   return 0;
 }
 
-static int
+int
 make_backsig(PKT_signature *sig,PKT_public_key *pk,
             PKT_public_key *sub_pk,PKT_secret_key *sub_sk)
 {
index 07935db..9eda7c5 100644 (file)
@@ -182,6 +182,8 @@ int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
 int keygen_upd_std_prefs( PKT_signature *sig, void *opaque );
 int keygen_add_keyserver_url(PKT_signature *sig, void *opaque);
 int keygen_add_revkey(PKT_signature *sig, void *opaque);
+int make_backsig(PKT_signature *sig,PKT_public_key *pk,
+                PKT_public_key *sub_pk,PKT_secret_key *sub_sk);
 int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
 #ifdef ENABLE_CARD_SUPPORT
 int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
index a50ab88..c5b9774 100644 (file)
@@ -979,7 +979,7 @@ parse_options(char *str,unsigned int *options,
       for(i=0;opts[i].name;i++)
         if(opts[i].help)
          printf("%s%*s%s\n",opts[i].name,
-                maxlen+2-strlen(opts[i].name),"",_(opts[i].help));
+                maxlen+2-(int)strlen(opts[i].name),"",_(opts[i].help));
 
       g10_exit(0);
     }