Silence several warnings when building under Windows.
[gnupg.git] / g10 / export.c
index 43856ff..fffaf79 100644 (file)
@@ -107,7 +107,7 @@ export_pubkeys_stream (ctrl_t ctrl, iobuf_t out, strlist_t users,
                       kbnode_t *keyblock_out, unsigned int options )
 {
   int any, rc;
-  
+
   rc = do_export_stream (ctrl, out, users, 0, keyblock_out, options, &any);
   if (!rc && !any)
     rc = -1;
@@ -197,10 +197,10 @@ do_export (ctrl_t ctrl, strlist_t users, int secret, unsigned int options )
   int any, rc;
   armor_filter_context_t *afx = NULL;
   compress_filter_context_t zfx;
-  
+
   memset( &zfx, 0, sizeof zfx);
-  
-  rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out );
+
+  rc = open_outfile (-1, NULL, 0, &out );
   if (rc)
     return rc;
 
@@ -251,7 +251,7 @@ subkey_in_list_p (subkey_list_t list, KBNODE node)
       u32 kid[2];
 
       keyid_from_pk (node->pkt->pkt.public_key, kid);
-      
+
       for (; list; list = list->next)
         if (list->kid[0] == kid[0] && list->kid[1] == kid[1])
           return 1;
@@ -293,17 +293,17 @@ exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
     case KEYDB_SEARCH_MODE_LONG_KID:
       keyid_from_pk (node->pkt->pkt.public_key, kid);
       break;
-      
+
     case KEYDB_SEARCH_MODE_FPR16:
     case KEYDB_SEARCH_MODE_FPR20:
     case KEYDB_SEARCH_MODE_FPR:
       fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
       break;
-      
+
     default:
       break;
     }
-  
+
   switch(desc->mode)
     {
     case KEYDB_SEARCH_MODE_SHORT_KID:
@@ -346,7 +346,7 @@ canon_pubkey_algo (int algo)
     case GCRY_PK_RSA:
     case GCRY_PK_RSA_E:
     case GCRY_PK_RSA_S: return GCRY_PK_RSA;
-    case GCRY_PK_ELG:   
+    case GCRY_PK_ELG:
     case GCRY_PK_ELG_E: return GCRY_PK_ELG;
     default: return algo;
     }
@@ -354,7 +354,7 @@ canon_pubkey_algo (int algo)
 
 
 /* Use the key transfer format given in S_PGP to create the secinfo
-   structure in PK and chnage the parameter array in PK to include the
+   structure in PK and change the parameter array in PK to include the
    secret parameters.  */
 static gpg_error_t
 transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
@@ -377,7 +377,6 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
   u32  s2k_count = 0;
   size_t npkey, nskey;
   gcry_mpi_t skey[10];  /* We support up to 9 parameters.  */
-  u16 desired_csum;
   int skeyidx = 0;
   struct seckey_info *ski;
 
@@ -415,7 +414,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
         goto bad_seckey;
       protect_algo = gcry_cipher_map_name (string);
       xfree (string);
-      
+
       value = gcry_sexp_nth_data (list, 3, &valuelen);
       if (!value || !valuelen || valuelen > sizeof iv)
         goto bad_seckey;
@@ -460,6 +459,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
       || gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
       || !npkey || npkey >= nskey || nskey > PUBKEY_MAX_NSKEY)
     goto bad_seckey;
+  pubkey_algo = map_pk_gcry_to_openpgp (pubkey_algo);
 
   gcry_sexp_release (list);
   list = gcry_sexp_find_token (top_list, "skey", 0);
@@ -507,21 +507,22 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
     }
   skey[skeyidx++] = NULL;
 
-  gcry_sexp_release (list);
-  list = gcry_sexp_find_token (top_list, "csum", 0);
-  if (list)
-    {
-      string = gcry_sexp_nth_string (list, 1);
-      if (!string)
-        goto bad_seckey;
-      desired_csum = strtoul (string, NULL, 10);
-      xfree (string);
-    }
-  else
-    desired_csum = 0;
+  gcry_sexp_release (list); list = NULL;
 
+  /* We have no need for the CSUM valuel thus we don't parse it.  */
+  /* list = gcry_sexp_find_token (top_list, "csum", 0); */
+  /* if (list) */
+  /*   { */
+  /*     string = gcry_sexp_nth_string (list, 1); */
+  /*     if (!string) */
+  /*       goto bad_seckey; */
+  /*     desired_csum = strtoul (string, NULL, 10); */
+  /*     xfree (string); */
+  /*   } */
+  /* else */
+  /*   desired_csum = 0; */
+  /* gcry_sexp_release (list); list = NULL; */
 
-  gcry_sexp_release (list); list = NULL;
   gcry_sexp_release (top_list); top_list = NULL;
 
   /* log_debug ("XXX is_v4=%d\n", is_v4); */
@@ -557,11 +558,79 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
       goto leave;
     }
 
+  /* We need to change the received parameters for ECC algorithms.
+     The transfer format has all parameters but OpenPGP defines that
+     only the OID of the curve is to be used.  */
+  if (pubkey_algo == PUBKEY_ALGO_ECDSA
+      || pubkey_algo == PUBKEY_ALGO_EDDSA
+      || pubkey_algo == PUBKEY_ALGO_ECDH)
+    {
+      gcry_sexp_t s_pubkey;
+      const char *curvename, *curveoidstr;
+      gcry_mpi_t mpi;
+
+      /* We build an S-expression with the public key parameters and
+         ask Libgcrypt to return the matching curve name.  */
+      if (npkey != 6 || !skey[0] || !skey[1] || !skey[2]
+          || !skey[3] || !skey[4] || !skey[5]
+          || !skey[6] || skey[7])
+        {
+          err = gpg_error (GPG_ERR_INTERNAL);
+          goto leave;
+        }
+      err = gcry_sexp_build (&s_pubkey, NULL,
+                             "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
+                             skey[0], skey[1], skey[2], skey[3], skey[4]);
+      if (err)
+        goto leave;
+      curvename = gcry_pk_get_curve (s_pubkey, 0, NULL);
+      gcry_sexp_release (s_pubkey);
+      curveoidstr = openpgp_curve_to_oid (curvename, NULL);
+      if (!curveoidstr)
+        {
+          log_error ("no OID known for curve '%s'\n", curvename);
+          err = gpg_error (GPG_ERR_UNKNOWN_NAME);
+          goto leave;
+        }
+      err = openpgp_oid_from_str (curveoidstr, &mpi);
+      if (err)
+        goto leave;
+
+      /* Now replace the curve parameters by the OID and shift the
+         rest of the parameters.  */
+      gcry_mpi_release (skey[0]);
+      skey[0] = mpi;
+      for (idx=1; idx <= 4; idx++)
+        gcry_mpi_release (skey[idx]);
+      skey[1] = skey[5];
+      skey[2] = skey[6];
+      for (idx=3; idx <= 6; idx++)
+        skey[idx] = NULL;
+
+      /* Fixup the NPKEY and NSKEY to match OpenPGP reality.  */
+      npkey = 2;
+      nskey = 3;
+
+      /* for (idx=0; skey[idx]; idx++) */
+      /*   { */
+      /*     log_info ("YYY skey[%d]:", idx); */
+      /*     if (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)) */
+      /*       { */
+      /*         void *p; */
+      /*         unsigned int nbits; */
+      /*         p = gcry_mpi_get_opaque (skey[idx], &nbits); */
+      /*         log_printhex (NULL, p, (nbits+7)/8); */
+      /*       } */
+      /*     else */
+      /*       gcry_mpi_dump (skey[idx]); */
+      /*     log_printf ("\n"); */
+      /*   } */
+    }
+
   /* Do some sanity checks.  */
-  if (s2k_count <= 1024)
+  if (s2k_count > 255)
     {
-      /* The count must be larger so that encode_s2k_iterations does
-         not fall into a backward compatibility mode.  */
+      /* We expect an already encoded S2K count.  */
       err = gpg_error (GPG_ERR_INV_DATA);
       goto leave;
     }
@@ -576,12 +645,11 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
   err = openpgp_md_test_algo (s2k_algo);
   if (err)
     goto leave;
-  
-  /* Check that the public key parameters match.  */
+
+  /* Check that the public key parameters match.  Note that since
+     Libgcrypt 1.5 gcry_mpi_cmp handles opaque MPI correctly.  */
   for (idx=0; idx < npkey; idx++)
-    if (gcry_mpi_get_flag (pk->pkey[idx], GCRYMPI_FLAG_OPAQUE)
-        || gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)
-        || gcry_mpi_cmp (pk->pkey[idx], skey[idx]))
+    if (gcry_mpi_cmp (pk->pkey[idx], skey[idx]))
       {
         err = gpg_error (GPG_ERR_BAD_PUBKEY);
         goto leave;
@@ -607,7 +675,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
       err = gpg_error_from_syserror ();
       goto leave;
     }
-  
+
   ski->is_protected = 1;
   ski->sha1chk = 1;
   ski->algo = protect_algo;
@@ -615,7 +683,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
   ski->s2k.hash_algo = s2k_algo;
   assert (sizeof ski->s2k.salt == sizeof s2k_salt);
   memcpy (ski->s2k.salt, s2k_salt, sizeof s2k_salt);
-  ski->s2k.count = encode_s2k_iterations (s2k_count);
+  ski->s2k.count = s2k_count;
   assert (ivlen <= sizeof ski->iv);
   memcpy (ski->iv, iv, ivlen);
   ski->ivlen = ivlen;
@@ -636,7 +704,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
  bad_seckey:
   err = gpg_error (GPG_ERR_BAD_SECKEY);
   goto leave;
-  
+
  outofmem:
   err = gpg_error (GPG_ERR_ENOMEM);
   goto leave;
@@ -671,7 +739,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
   init_packet (&pkt);
   kdbhd = keydb_new ();
 
-  if (!users) 
+  if (!users)
     {
       ndesc = 1;
       desc = xcalloc (ndesc, sizeof *desc);
@@ -679,13 +747,13 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
     }
   else
     {
-      for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) 
+      for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
         ;
       desc = xmalloc ( ndesc * sizeof *desc);
-        
+
       for (ndesc=0, sl=users; sl; sl = sl->next)
         {
-          if (!(err=classify_user_id (sl->d, desc+ndesc)))
+          if (!(err=classify_user_id (sl->d, desc+ndesc, 1)))
             ndesc++;
           else
             log_error (_("key \"%s\" not found: %s\n"),
@@ -708,7 +776,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
       goto leave;
     }
 #endif
-  
+
   /* For secret key export we need to setup a decryption context.  */
   if (secret)
     {
@@ -721,7 +789,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
           log_error ("error getting the KEK: %s\n", gpg_strerror (err));
           goto leave;
         }
-      
+
       /* Prepare a cipher context.  */
       err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
                               GCRY_CIPHER_MODE_AESWRAP, 0);
@@ -737,20 +805,20 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
       kek = NULL;
     }
 
-  while (!(err = keydb_search2 (kdbhd, desc, ndesc, &descindex))) 
+  while (!(err = keydb_search (kdbhd, desc, ndesc, &descindex)))
     {
       int skip_until_subkey = 0;
       u32 keyid[2];
       PKT_public_key *pk;
 
-      if (!users) 
+      if (!users)
         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
 
       /* Read the keyblock. */
       release_kbnode (keyblock);
       keyblock = NULL;
       err = keydb_get_keyblock (kdbhd, &keyblock);
-      if (err) 
+      if (err)
         {
           log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
           goto leave;
@@ -802,7 +870,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
         clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
 
       /* And write it. */
-      for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); ) 
+      for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
         {
           if (skip_until_subkey)
             {
@@ -835,7 +903,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
                      subkey and include that subkey into the output
                      too.  Need to add this subkey to a list so that
                      it won't get processed a second time.
-                   
+
                      So the first step here is to check that list and
                      skip in any case if the key is in that list.
 
@@ -843,7 +911,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
                      function of GnuPG < 2.1 is not able to merge
                      secret keys and thus it is useless to output them
                      as two separate keys and have import merge them.  */
-                  if (subkey_in_list_p (subkey_list, node))  
+                  if (subkey_in_list_p (subkey_list, node))
                     skip_until_subkey = 1; /* Already processed this one. */
                   else
                     {
@@ -854,7 +922,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
                             && exact_subkey_match_p (desc+j, node))
                           break;
                       if (!(j < ndesc))
-                        skip_until_subkey = 1; /* No other one matching. */ 
+                        skip_until_subkey = 1; /* No other one matching. */
                     }
                 }
 
@@ -885,7 +953,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
                   && node->pkt->pkt.signature->revkey)
                 {
                   int i;
-                  
+
                   for (i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
                     if ( (node->pkt->pkt.signature->revkey[i]->class & 0x40))
                       break;
@@ -904,7 +972,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
                 or a signature on an attrib */
              while (kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE)
                 kbctx = kbctx->next;
+
              continue;
            }
 
@@ -913,7 +981,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
             {
               u32 subkidbuf[2], *subkid;
               char *hexgrip, *serialno;
-              
+
               pk = node->pkt->pkt.public_key;
               if (node->pkt->pkttype == PKT_PUBLIC_KEY)
                 subkid = NULL;
@@ -930,7 +998,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
                   skip_until_subkey = 1;
                   continue;
                 }
-              
+
               err = hexkeygrip_from_pk (pk, &hexgrip);
               if (err)
                 {
@@ -970,7 +1038,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
                   /* Create a key stub.  */
                   struct seckey_info *ski;
                   const char *s;
-                  
+
                   pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
                   if (!ski)
                     {
@@ -989,7 +1057,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
                            ski->ivlen++, s += 2)
                         ski->iv[ski->ivlen] = xtoi_2 (s);
                     }
-                  
+
                   if ((options&EXPORT_SEXP_FORMAT))
                     err = build_sexp (out, node->pkt, &indent);
                   else
@@ -1032,7 +1100,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
                   realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
                   if (!realkeylen)
                     goto unwraperror; /* Invalid csexp.  */
-                  
+
                   err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
                   xfree (key);
                   key = NULL;
@@ -1119,7 +1187,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
         iobuf_put (out, ')');
       iobuf_put (out, '\n');
     }
-  if (err == -1)
+  if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
     err = 0;
 
  leave:
@@ -1215,6 +1283,16 @@ build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
   /*     (*indent)--; */
   /*   } */
+  /* else if (sk->pubkey_algo == PUBKEY_ALGO_ECDSA && !sk->is_protected) */
+  /*   { */
+  /*     write_sexp_line (out, indent, "(ecdsa\n"); */
+  /*     (*indent)++;  */
+  /*     write_sexp_keyparm (out, indent, "c", sk->skey[0]); iobuf_put (out,'\n'); */
+  /*     write_sexp_keyparm (out, indent, "q", sk->skey[6]); iobuf_put (out,'\n'); */
+  /*     write_sexp_keyparm (out, indent, "d", sk->skey[7]); */
+  /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
+  /*     (*indent)--; */
+  /*   } */
   /* else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected) */
   /*   { */
   /*     write_sexp_line (out, indent, "(elg\n"); */
@@ -1242,7 +1320,7 @@ build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
 
 /* For some packet types we write them in a S-expression format.  This
    is still EXPERIMENTAL and subject to change.  */
-static int 
+static int
 build_sexp (iobuf_t out, PACKET *pkt, int *indent)
 {
   int rc;