* main.h, seskey.c (encode_md_value): Modify to allow a q size greater
[gnupg.git] / g10 / sign.c
index 814f381..925fef4 100644 (file)
@@ -1,6 +1,6 @@
 /* sign.c - sign data
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
- *               2004 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ *               2006 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -16,7 +16,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
@@ -54,9 +55,9 @@ void __stdcall Sleep(ulong);
 static int recipient_digest_algo=0;
 
 /****************
- * Create a notation.  It is assumed that the stings in STRLIST
- * are already checked to contain only printable data and have a valid
- * NAME=VALUE format.
+ * Create notations and other stuff.  It is assumed that the stings in
+ * STRLIST are already checked to contain only printable data and have
+ * a valid NAME=VALUE format.
  */
 static void
 mk_notation_policy_etc( PKT_signature *sig,
@@ -64,9 +65,8 @@ mk_notation_policy_etc( PKT_signature *sig,
 {
     const char *string;
     char *s=NULL;
-    byte *buf;
-    unsigned n1, n2;
-    STRLIST nd=NULL,pu=NULL;
+    STRLIST pu=NULL;
+    struct notation *nd=NULL;
     struct expando_args args;
 
     memset(&args,0,sizeof(args));
@@ -79,57 +79,43 @@ mk_notation_policy_etc( PKT_signature *sig,
        good to do these checks anyway. */
 
     /* notation data */
-    if(IS_SIG(sig) && opt.sig_notation_data)
+    if(IS_SIG(sig) && opt.sig_notations)
       {
        if(sig->version<4)
          log_error(_("can't put notation data into v3 (PGP 2.x style) "
                      "signatures\n"));
        else
-         nd=opt.sig_notation_data;
+         nd=opt.sig_notations;
       }
-    else if( IS_CERT(sig) && opt.cert_notation_data )
+    else if( IS_CERT(sig) && opt.cert_notations )
       {
        if(sig->version<4)
          log_error(_("can't put notation data into v3 (PGP 2.x style) "
                      "key signatures\n"));
        else
-         nd=opt.cert_notation_data;
+         nd=opt.cert_notations;
       }
 
-    for( ; nd; nd = nd->next ) {
-        char *expanded;
-
-        string = nd->d;
-       s = strchr( string, '=' );
-       if( !s )
-         BUG(); /* we have already parsed this */
-       n1 = s - string;
-       s++;
+    if(nd)
+      {
+       struct notation *i;
 
-       expanded=pct_expando(s,&args);
-       if(!expanded)
+       for(i=nd;i;i=i->next)
          {
-           log_error(_("WARNING: unable to %%-expand notation "
-                       "(too large).  Using unexpanded.\n"));
-           expanded=m_strdup(s);
+           i->altvalue=pct_expando(i->value,&args);
+           if(!i->altvalue)
+             log_error(_("WARNING: unable to %%-expand notation "
+                         "(too large).  Using unexpanded.\n"));
          }
 
-       n2 = strlen(expanded);
-       buf = m_alloc( 8 + n1 + n2 );
-       buf[0] = 0x80; /* human readable */
-       buf[1] = buf[2] = buf[3] = 0;
-       buf[4] = n1 >> 8;
-       buf[5] = n1;
-       buf[6] = n2 >> 8;
-       buf[7] = n2;
-       memcpy(buf+8, string, n1 );
-       memcpy(buf+8+n1, expanded, n2 );
-       build_sig_subpkt( sig, SIGSUBPKT_NOTATION
-                         | ((nd->flags & 1)? SIGSUBPKT_FLAG_CRITICAL:0),
-                         buf, 8+n1+n2 );
-       m_free(expanded);
-       m_free(buf);
-    }
+       keygen_add_notations(sig,nd);
+
+       for(i=nd;i;i=i->next)
+         {
+           xfree(i->altvalue);
+           i->altvalue=NULL;
+         }
+      }
 
     /* set policy URL */
     if( IS_SIG(sig) && opt.sig_policy_url )
@@ -158,14 +144,14 @@ mk_notation_policy_etc( PKT_signature *sig,
          {
            log_error(_("WARNING: unable to %%-expand policy URL "
                        "(too large).  Using unexpanded.\n"));
-           s=m_strdup(string);
+           s=xstrdup(string);
          }
 
        build_sig_subpkt(sig,SIGSUBPKT_POLICY|
                         ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0),
                         s,strlen(s));
 
-       m_free(s);
+       xfree(s);
       }
 
     /* preferred keyserver URL */
@@ -186,14 +172,14 @@ mk_notation_policy_etc( PKT_signature *sig,
          {
            log_error(_("WARNING: unable to %%-expand preferred keyserver URL"
                        " (too large).  Using unexpanded.\n"));
-           s=m_strdup(string);
+           s=xstrdup(string);
          }
 
        build_sig_subpkt(sig,SIGSUBPKT_PREF_KS|
                         ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0),
                         s,strlen(s));
 
-       m_free(s);
+       xfree(s);
       }
 }
 
@@ -333,8 +319,17 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
       }
     else 
       {
-        frame = encode_md_value( sk->pubkey_algo, md,
-                                 digest_algo, mpi_get_nbits(sk->skey[0]) );
+       /* TODO: remove this check in the future once all the
+          variable-q DSA stuff makes it into the standard. */
+       if(!opt.expert
+          && sk->pubkey_algo==PUBKEY_ALGO_DSA
+          && md_digest_length(digest_algo)!=20)
+         {
+           log_error(_("DSA requires the use of a 160 bit hash algorithm\n"));
+           return G10ERR_GENERAL;
+         }
+
+        frame = encode_md_value( NULL, sk, md, digest_algo );
         if (!frame)
           return G10ERR_GENERAL;
         rc = pubkey_sign( sk->pubkey_algo, sig->data, frame, sk->skey );
@@ -345,14 +340,12 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
         /* check that the signature verification worked and nothing is
          * fooling us e.g. by a bug in the signature create
          * code or by deliberately introduced faults. */
-        PKT_public_key *pk = m_alloc_clear (sizeof *pk);
+        PKT_public_key *pk = xmalloc_clear (sizeof *pk);
 
         if( get_pubkey( pk, sig->keyid ) )
             rc = G10ERR_NO_PUBKEY;
         else {
-            frame = encode_md_value (pk->pubkey_algo, md,
-                                     sig->digest_algo,
-                                     mpi_get_nbits(pk->pkey[0]) );
+           frame = encode_md_value (pk, NULL, md, sig->digest_algo );
             if (!frame)
                 rc = G10ERR_GENERAL;
             else
@@ -374,7 +367,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
                     pubkey_algo_to_string(sk->pubkey_algo),
                     digest_algo_to_string(sig->digest_algo),
                     ustr );
-           m_free(ustr);
+           xfree(ustr);
        }
     }
     return rc;
@@ -406,21 +399,20 @@ complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md )
 */
 
 static int
-hash_for(int pubkey_algo, int packet_version )
+hash_for(PKT_secret_key *sk)
 {
   if( opt.def_digest_algo )
     return opt.def_digest_algo;
   else if( recipient_digest_algo )
     return recipient_digest_algo;
-  else if(PGP2 && pubkey_algo == PUBKEY_ALGO_RSA && packet_version < 4 )
-    {
-      /* Old-style PGP only understands MD5 */
-      return DIGEST_ALGO_MD5;
-    }
-  else if( pubkey_algo == PUBKEY_ALGO_DSA )
+  else if(sk->pubkey_algo==PUBKEY_ALGO_DSA
+         || (sk->is_protected && sk->protect.s2k.mode==1002))
     {
-      /* We need a 160-bit hash for DSA, so we can't just take the first
-        in the pref list */
+      /* The sk lives on a smartcard, or it's a DSA key.  DSA requires
+        a 160-bit hash, and current smartcards only handle SHA-1 and
+        RIPEMD/160 (i.e. 160-bit hashes).  This is correct now, but
+        may need revision as the cards add algorithms and/or DSA is
+        expanded to use larger hashes. */
 
       if(opt.personal_digest_prefs)
        {
@@ -433,6 +425,11 @@ hash_for(int pubkey_algo, int packet_version )
 
       return DIGEST_ALGO_SHA1;
     }
+  else if(PGP2 && sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 )
+    {
+      /* Old-style PGP only understands MD5 */
+      return DIGEST_ALGO_MD5;
+    }
   else if( opt.personal_digest_prefs )
     {
       /* It's not DSA, so we can use whatever the first hash algorithm
@@ -508,9 +505,9 @@ write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass )
         }
 
         sk = sk_rover->sk;
-        ops = m_alloc_clear (sizeof *ops);
+        ops = xmalloc_clear (sizeof *ops);
         ops->sig_class = sigclass;
-        ops->digest_algo = hash_for (sk->pubkey_algo, sk->version);
+        ops->digest_algo = hash_for (sk);
         ops->pubkey_algo = sk->pubkey_algo;
         keyid_from_sk (sk, ops->keyid);
         ops->last = (skcount == 1);
@@ -545,13 +542,13 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
             char *s = make_basename (opt.set_filename? opt.set_filename
                                                      : fname,
                                      iobuf_get_real_fname(inp));
-            pt = m_alloc (sizeof *pt + strlen(s) - 1);
+            pt = xmalloc (sizeof *pt + strlen(s) - 1);
             pt->namelen = strlen (s);
             memcpy (pt->name, s, pt->namelen);
-            m_free (s);
+            xfree (s);
         }
         else { /* no filename */
-            pt = m_alloc (sizeof *pt - 1);
+            pt = xmalloc (sizeof *pt - 1);
             pt->namelen = 0;
         }
     }
@@ -560,8 +557,10 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
     if ( !iobuf_is_pipe_filename (fname) && *fname )
       {
         off_t tmpsize;
-       
-        if( !(tmpsize = iobuf_get_filelength(inp)) )
+        int overflow;
+
+        if( !(tmpsize = iobuf_get_filelength(inp, &overflow))
+            && !overflow )
          log_info (_("WARNING: `%s' is an empty file\n"), fname);
 
         /* We can't encode the length of very large files because
@@ -639,16 +638,16 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash,
        sk = sk_rover->sk;
 
        /* build the signature packet */
-       sig = m_alloc_clear (sizeof *sig);
+       sig = xmalloc_clear (sizeof *sig);
        if(opt.force_v3_sigs || RFC1991)
          sig->version=3;
        else if(duration || opt.sig_policy_url
-               || opt.sig_notation_data || opt.sig_keyserver_url)
+               || opt.sig_notations || opt.sig_keyserver_url)
          sig->version=4;
        else
          sig->version=sk->version;
        keyid_from_sk (sk, sig->keyid);
-       sig->digest_algo = hash_for (sk->pubkey_algo, sk->version);
+       sig->digest_algo = hash_for(sk);
        sig->pubkey_algo = sk->pubkey_algo;
        if(timestamp)
          sig->timestamp = timestamp;
@@ -667,7 +666,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash,
         hash_sigversion_to_magic (md, sig);
        md_final (md);
 
-       rc = do_sign( sk, sig, md, hash_for (sig->pubkey_algo, sk->version) );
+       rc = do_sign( sk, sig, md, hash_for (sk) );
        md_close (md);
 
        if( !rc ) { /* and write it */
@@ -744,8 +743,13 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
        && (rc=setup_symkey(&efx.symkey_s2k,&efx.symkey_dek)))
       goto leave;
 
-    if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991)
-      duration=ask_expire_interval(1);
+    if(!opt.force_v3_sigs && !RFC1991)
+      {
+       if(opt.ask_sig_expire && !opt.batch)
+         duration=ask_expire_interval(1,opt.def_sig_expire);
+       else
+         duration=parse_expire_string(opt.def_sig_expire);
+      }
 
     if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) )
        goto leave;
@@ -808,6 +812,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
       }
 
     mfx.md = md_open(0, 0);
+    if (DBG_HASHING)
+       md_start_debug (mfx.md, "sign");
 
    /* If we're encrypting and signing, it is reasonable to pick the
        hash algorithm to use out of the recepient key prefs. */
@@ -836,8 +842,14 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
               sk, but so long as there is only one signing algorithm
               with hash restrictions, this is ok. -dms */
 
+           /* Current smartcards only do 160-bit hashes as well.
+              Note that this may well have to change as the cards add
+              algorithms. */
+
            for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next )
-             if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA)
+             if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA
+                || (sk_rover->sk->is_protected
+                    && sk_rover->sk->protect.s2k.mode==1002))
                hashlen=20;
 
            if((algo=
@@ -849,7 +861,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
 
     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
        PKT_secret_key *sk = sk_rover->sk;
-       md_enable(mfx.md, hash_for(sk->pubkey_algo, sk->version ));
+       md_enable(mfx.md, hash_for(sk));
     }
 
     if( !multifile )
@@ -1007,8 +1019,13 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
     memset( &afx, 0, sizeof afx);
     init_packet( &pkt );
 
-    if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991)
-      duration=ask_expire_interval(1);
+    if(!opt.force_v3_sigs && !RFC1991)
+      {
+       if(opt.ask_sig_expire && !opt.batch)
+         duration=ask_expire_interval(1,opt.def_sig_expire);
+       else
+         duration=parse_expire_string(opt.def_sig_expire);
+      }
 
     if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) )
        goto leave;
@@ -1062,7 +1079,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
 
     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
        PKT_secret_key *sk = sk_rover->sk;
-       if( hash_for(sk->pubkey_algo, sk->version) == DIGEST_ALGO_MD5 )
+       if( hash_for(sk) == DIGEST_ALGO_MD5 )
            only_md5 = 1;
        else {
            only_md5 = 0;
@@ -1079,7 +1096,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
        iobuf_writestr(out, "Hash: " );
        for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
            PKT_secret_key *sk = sk_rover->sk;
-           int i = hash_for(sk->pubkey_algo, sk->version);
+           int i = hash_for(sk);
 
            if( !hashs_seen[ i & 0xff ] ) {
                s = digest_algo_to_string( i );
@@ -1104,7 +1121,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
     textmd = md_open(0, 0);
     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
        PKT_secret_key *sk = sk_rover->sk;
-       md_enable(textmd, hash_for(sk->pubkey_algo, sk->version));
+       md_enable(textmd, hash_for(sk));
     }
     if ( DBG_HASHING )
        md_start_debug( textmd, "clearsign" );
@@ -1161,8 +1178,13 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
     memset( &cfx, 0, sizeof cfx);
     init_packet( &pkt );
 
-    if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991)
-      duration=ask_expire_interval(1);
+    if(!opt.force_v3_sigs && !RFC1991)
+      {
+       if(opt.ask_sig_expire && !opt.batch)
+         duration=ask_expire_interval(1,opt.def_sig_expire);
+       else
+         duration=parse_expire_string(opt.def_sig_expire);
+      }
 
     rc = build_sk_list (locusr, &sk_list, 1, PUBKEY_USAGE_SIG);
     if (rc) 
@@ -1185,7 +1207,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
     handle_progress (&pfx, inp, fname);
 
     /* prepare key */
-    s2k = m_alloc_clear( sizeof *s2k );
+    s2k = xmalloc_clear( sizeof *s2k );
     s2k->mode = RFC1991? 0:opt.s2k_mode;
     s2k->hash_algo = S2K_DIGEST_ALGO;
 
@@ -1217,10 +1239,12 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
     if (opt.textmode)
        iobuf_push_filter (inp, text_filter, &tfx);
     mfx.md = md_open(0, 0);
+    if ( DBG_HASHING )
+       md_start_debug (mfx.md, "symc-sign");
 
     for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) {
        PKT_secret_key *sk = sk_rover->sk;
-       md_enable (mfx.md, hash_for (sk->pubkey_algo, sk->version ));
+       md_enable (mfx.md, hash_for (sk));
     }
 
     iobuf_push_filter (inp, md_filter, &mfx);
@@ -1232,7 +1256,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
     /* Write the symmetric key packet */
     /*(current filters: armor)*/
     if (!RFC1991) {
-       PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc );
+       PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc );
        enc->version = 4;
        enc->cipher_algo = cfx.dek->algo;
        enc->s2k = *s2k;
@@ -1240,7 +1264,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
        pkt.pkt.symkey_enc = enc;
        if( (rc = build_packet( out, &pkt )) )
            log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
-       m_free(enc);
+       xfree(enc);
     }
 
     /* Push the encryption filter */
@@ -1284,8 +1308,8 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
     iobuf_close(inp);
     release_sk_list( sk_list );
     md_close( mfx.md );
-    m_free(cfx.dek);
-    m_free(s2k);
+    xfree(cfx.dek);
+    xfree(s2k);
     return rc;
 }
 
@@ -1342,9 +1366,8 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
 
        if(opt.cert_digest_algo)
          digest_algo=opt.cert_digest_algo;
-       else if((sk->pubkey_algo==PUBKEY_ALGO_RSA ||
-                sk->pubkey_algo==PUBKEY_ALGO_RSA_S) &&
-               pk->version<4 && sigversion < 4)
+       else if(sk->pubkey_algo==PUBKEY_ALGO_RSA
+               && pk->version<4 && sigversion<4)
          digest_algo = DIGEST_ALGO_MD5;
        else
          digest_algo = DIGEST_ALGO_SHA1;
@@ -1366,7 +1389,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
         hash_uid (md, sigversion, uid);
       }
     /* and make the signature packet */
-    sig = m_alloc_clear( sizeof *sig );
+    sig = xmalloc_clear( sizeof *sig );
     sig->version = sigversion;
     sig->flags.exportable=1;
     sig->flags.revocable=1;