gpg: Set a limit for a WKD import of 256 KiB.
[gnupg.git] / g10 / seskey.c
index 1f3e8ab..1549017 100644 (file)
@@ -1,4 +1,4 @@
-/* seskey.c -  make sesssion keys etc.
+/* seskey.c -  make session keys etc.
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
  *               2006, 2009, 2010 Free Software Foundation, Inc.
  *
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 
 #include "gpg.h"
-#include "util.h"
-#include "cipher.h"
+#include "../common/util.h"
 #include "options.h"
 #include "main.h"
-#include "i18n.h"
+#include "../common/i18n.h"
 
 
-/****************
- * Make a session key and put it into DEK
- */
+/* Generate a new session key in *DEK that is appropriate for the
+ * algorithm DEK->ALGO (i.e., ensure that the key is not weak).
+ *
+ * This function overwrites DEK->KEYLEN, DEK->KEY.  The rest of the
+ * fields are left as is.  */
 void
 make_session_key( DEK *dek )
 {
@@ -68,11 +68,12 @@ make_session_key( DEK *dek )
 }
 
 
-/****************
- * Encode the session key. NBITS is the number of bits which should be used
- * for packing the session key.
- * returns: A mpi with the session key (caller must free)
- */
+/* Encode the session key stored in DEK as an MPI in preparation to
+ * encrypt it with the public key algorithm OPENPGP_PK_ALGO with a key
+ * whose length (the size of the public key) is NBITS.
+ *
+ * On success, returns an MPI, which the caller must free using
+ * gcry_mpi_release().  */
 gcry_mpi_t
 encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
 {
@@ -83,7 +84,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
   u16 csum;
   gcry_mpi_t a;
 
-  if (DBG_CIPHER)
+  if (DBG_CRYPTO)
     log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen);
 
   csum = 0;
@@ -104,7 +105,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
                   + 7 ) & (~7));
 
       /* alg+key+csum fit and the size is congruent to 8.  */
-      assert (!(nframe%8) && nframe > 1 + dek->keylen + 2 );
+      log_assert (!(nframe%8) && nframe > 1 + dek->keylen + 2 );
 
       frame = xmalloc_secure (nframe);
       n = 0;
@@ -115,12 +116,12 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
       frame[n++] = csum;
       i = nframe - n;         /* Number of padded bytes.  */
       memset (frame+n, i, i); /* Use it as the value of each padded byte.  */
-      assert (n+i == nframe);
+      log_assert (n+i == nframe);
 
-      if (DBG_CIPHER)
+      if (DBG_CRYPTO)
         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))
@@ -137,14 +138,15 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
     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:
+  /* We encode the session key according to PKCS#1 v1.5 (see section
+   * 13.1.1 of RFC 4880):
    *
-   *      0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
+   *      0  2  RND(i bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
    *
    * (But how can we store the leading 0 - the external representaion
    *  of MPIs doesn't allow leading zeroes =:-)
    *
-   * RND are non-zero random bytes.
+   * RND are (at least 1) non-zero random bytes.
    * A   is the cipher algorithm
    * DEK is the encryption key (session key) length k depends on the
    *      cipher algorithm (20 is used with blowfish160).
@@ -155,8 +157,10 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
   n = 0;
   frame[n++] = 0;
   frame[n++] = 2;
+  /* The number of random bytes are the number of otherwise unused
+     bytes.  See diagram above.  */
   i = nframe - 6 - dek->keylen;
-  assert( i > 0 );
+  log_assert( i > 0 );
   p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
   /* Replace zero bytes by new values.  */
   for (;;)
@@ -190,7 +194,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
   n += dek->keylen;
   frame[n++] = csum >>8;
   frame[n++] = csum;
-  assert (n == nframe);
+  log_assert (n == nframe);
   if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe))
     BUG();
   xfree (frame);
@@ -207,9 +211,12 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
     int i,n;
     gcry_mpi_t a;
 
-    if( len + asnlen + 4  > nframe )
-      log_bug ("can't encode a %d bit MD into a %d bits frame, algo=%d\n",
-               (int)(len*8), (int)nbits, algo);
+    if (len + asnlen + 4  > nframe)
+      {
+        log_error ("can't encode a %d bit MD into a %d bits frame, algo=%d\n",
+                   (int)(len*8), (int)nbits, algo);
+        return NULL;
+      }
 
     /* We encode the MD in this way:
      *
@@ -222,12 +229,12 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
     frame[n++] = 0;
     frame[n++] = 1; /* block type */
     i = nframe - len - asnlen -3 ;
-    assert( i > 1 );
+    log_assert( i > 1 );
     memset( frame+n, 0xff, i ); n += i;
     frame[n++] = 0;
     memcpy( frame+n, asn, asnlen ); n += asnlen;
     memcpy( frame+n, gcry_md_read (md, algo), len ); n += len;
-    assert( n == nframe );
+    log_assert( n == nframe );
 
     if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe ))
        BUG();
@@ -256,27 +263,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;
-
-  assert (hash_algo);
-  assert (pk);
+  size_t mdlen;
 
-  pkalgo = map_pk_openpgp_to_gcry (pk->pubkey_algo);
+  log_assert (hash_algo);
+  log_assert (pk);
 
-  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 +301,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 change 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