gpg: Auto-create revocation certificates.
[gnupg.git] / g10 / seskey.c
index 2d7918d..410f0bf 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "gpg.h"
 #include "util.h"
-#include "cipher.h"
 #include "options.h"
 #include "main.h"
 #include "i18n.h"
@@ -49,10 +48,10 @@ make_session_key( DEK *dek )
                                 0 : GCRY_CIPHER_ENABLE_SYNC))) )
       BUG();
     gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
-    for (i=0; i < 16; i++ ) 
+    for (i=0; i < 16; i++ )
       {
        rc = gcry_cipher_setkey (chd, dek->key, dek->keylen);
-       if (!rc) 
+       if (!rc)
           {
            gcry_cipher_close (chd);
            return;
@@ -82,7 +81,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
   int i,n;
   u16 csum;
   gcry_mpi_t a;
-  
+
   if (DBG_CIPHER)
     log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen);
 
@@ -102,10 +101,10 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
        */
       nframe = (( 1 + dek->keylen + 2 /* The value so far is always odd. */
                   + 7 ) & (~7));
-      
+
       /* alg+key+csum fit and the size is congruent to 8.  */
       assert (!(nframe%8) && nframe > 1 + dek->keylen + 2 );
-      
+
       frame = xmalloc_secure (nframe);
       n = 0;
       frame[n++] = dek->algo;
@@ -120,15 +119,15 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
       if (DBG_CIPHER)
         log_debug ("encode_session_key: "
                    "[%d] %02x  %02x %02x ...  %02x %02x %02x\n",
-                   nframe, frame[0], frame[1], frame[2],
+                   (int) nframe, frame[0], frame[1], frame[2],
                    frame[nframe-3], frame[nframe-2], frame[nframe-1]);
-      
+
       if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, nframe, &nframe))
         BUG();
       xfree(frame);
       return a;
     }
-  
+
   /* The current limitation is that we can only use a session key
    * whose length is a multiple of BITS_PER_MPI_LIMB
    * I think we can live with that.
@@ -136,7 +135,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
   if (dek->keylen + 7 > nframe || !nframe)
     log_bug ("can't encode a %d bit key in a %d bits frame\n",
              dek->keylen*8, nbits );
-  
+
   /* We encode the session key in this way:
    *
    *      0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
@@ -163,7 +162,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
     {
       int j, k;
       byte *pp;
-      
+
       /* Count the zero bytes. */
       for (j=k=0; j < i; j++ )
         if (!p[j])
@@ -256,27 +255,32 @@ gcry_mpi_t
 encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
 {
   gcry_mpi_t frame;
-  int pkalgo;
+  size_t mdlen;
 
   assert (hash_algo);
   assert (pk);
 
-  pkalgo = map_pk_openpgp_to_gcry (pk->pubkey_algo);
-
-  if (pkalgo == GCRY_PK_DSA || pkalgo == GCRY_PK_ECDSA)
+  if (pk->pubkey_algo == PUBKEY_ALGO_EDDSA)
+    {
+      /* EdDSA signs data of arbitrary length.  Thus no special
+         treatment is required.  */
+      frame = gcry_mpi_set_opaque_copy (NULL, gcry_md_read (md, hash_algo),
+                                        8*gcry_md_get_algo_dlen (hash_algo));
+    }
+  else if (pk->pubkey_algo == PUBKEY_ALGO_DSA
+           || pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
     {
       /* It's a DSA signature, so find out the size of q.  */
 
-      size_t qbytes = gcry_mpi_get_nbits (pk->pkey[1]);
+      size_t qbits = gcry_mpi_get_nbits (pk->pkey[1]);
 
       /* pkey[1] is Q for ECDSA, which is an uncompressed point,
          i.e.  04 <x> <y>  */
-      if (pkalgo == GCRY_PK_ECDSA)
-        qbytes = ecdsa_qbits_from_Q (qbytes);
-      
+      if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
+        qbits = ecdsa_qbits_from_Q (qbits);
+
       /* Make sure it is a multiple of 8 bits. */
-      
-      if (qbytes%8)
+      if ((qbits%8))
        {
          log_error(_("DSA requires the hash length to be a"
                      " multiple of 8 bits\n"));
@@ -289,43 +293,38 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
         or something like that, which would look correct but allow
         trivial forgeries.  Yes, I know this rules out using MD5 with
         DSA. ;) */
-      if (qbytes < 160)
+      if (qbits < 160)
        {
          log_error (_("%s key %s uses an unsafe (%zu bit) hash\n"),
-                     gcry_pk_algo_name (pkalgo), keystr_from_pk (pk), qbytes);
+                     openpgp_pk_algo_name (pk->pubkey_algo),
+                     keystr_from_pk (pk), qbits);
          return NULL;
        }
-      
-      qbytes /= 8;
+
+
+      /* ECDSA 521 is special has it is larger than the largest hash
+         we have (SHA-512).  Thus we chnage the size for further
+         processing to 512.  */
+      if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA && qbits > 512)
+        qbits = 512;
 
       /* Check if we're too short.  Too long is safe as we'll
-        automatically left-truncate. 
-
-         FIXME:  Check against FIPS.
-         This checks would require the use of SHA512 with ECDSA 512.  I
-         think this is overkill to fail in this case.  Therefore,
-         relax the check, but only for ECDSA keys. We may need to
-         adjust it later for general case.  (Note that the check will
-         never pass for ECDSA 521 anyway as the only hash that
-         intended to match it is SHA 512, but 512 < 521).  */
-      if (gcry_md_get_algo_dlen (hash_algo) 
-          < ((pkalgo == GCRY_PK_ECDSA && qbytes > (521)/8) ? 512/8 : qbytes))
+        automatically left-truncate.  */
+      mdlen = gcry_md_get_algo_dlen (hash_algo);
+      if (mdlen < qbits/8)
        {
          log_error (_("%s key %s requires a %zu bit or larger hash "
-                       "(hash is %s\n"),
-                     gcry_pk_algo_name (pkalgo),
-                     keystr_from_pk(pk), qbytes*8,
+                       "(hash is %s)\n"),
+                     openpgp_pk_algo_name (pk->pubkey_algo),
+                     keystr_from_pk (pk), qbits,
                      gcry_md_algo_name (hash_algo));
          return NULL;
        }
 
-      /* By passing QBYTES as length to mpi_scan, we do the truncation
-         of the hash.
-
-         Note that in case of ECDSA 521 the hash is always smaller
-         than the key size.  */
+     /* Note that we do the truncation by passing QBITS/8 as length to
+        mpi_scan.  */
       if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG,
-                         gcry_md_read (md, hash_algo), qbytes, &qbytes))
+                         gcry_md_read (md, hash_algo), qbits/8, NULL))
         BUG();
     }
   else