[git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-413-g359c643

by Werner Koch cvs at cvs.gnupg.org
Wed May 7 15:06:56 CEST 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  359c643d747c890f73f68b42e0aeb896016f05fd (commit)
       via  e73edfb1759d05121ea66f67c775e763bf47d737 (commit)
       via  e5279c85a04084a2277acb224bd4ca3026dcafd4 (commit)
       via  09055aa0f7993aaf4dcffdd80d8192945ae6080a (commit)
       via  8fee6c1ce6d116fe7909dbe1184d95bc91305484 (commit)
       via  bdb9c2b314400da9155b8a924e22e486793dda89 (commit)
       via  a63ed9875830e5b3b4d48b7d97d24c18de36b326 (commit)
       via  6477e51919ef97f0f9cc05d10cdc7aa2b89faafe (commit)
      from  60e2fc7d38d8b37d1de944cf230e410c2ce37d5e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 359c643d747c890f73f68b42e0aeb896016f05fd
Author: Werner Koch <wk at gnupg.org>
Date:   Wed May 7 15:05:34 2014 +0200

    gpg: Print the key algorithm/curve with signature info.
    
    * g10/mainproc.c (check_sig_and_print): Print the name and curve.

diff --git a/g10/mainproc.c b/g10/mainproc.c
index d4a0549..28bb05e 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1564,6 +1564,9 @@ check_sig_and_print (CTX c, KBNODE node)
   int rc;
   int is_expkey = 0;
   int is_revkey = 0;
+  char pkstrbuf[PUBKEY_STRING_SIZE];
+
+  *pkstrbuf = 0;
 
   if (opt.skip_verify)
     {
@@ -1843,6 +1846,8 @@ check_sig_and_print (CTX c, KBNODE node)
             log_printf (" [%s]\n",trust_value_to_string(valid));
           else
             log_printf ("\n");
+
+          pubkey_string (pk, pkstrbuf, sizeof pkstrbuf);
           count++;
 	}
 
@@ -2017,10 +2022,12 @@ check_sig_and_print (CTX c, KBNODE node)
         log_info (_("Signature expires %s\n"), asctimestamp(sig->expiredate));
 
       if (opt.verbose)
-        log_info (_("%s signature, digest algorithm %s\n"),
+        log_info (_("%s signature, digest algorithm %s%s%s\n"),
                   sig->sig_class==0x00?_("binary"):
                   sig->sig_class==0x01?_("textmode"):_("unknown"),
-                  gcry_md_algo_name (sig->digest_algo));
+                  gcry_md_algo_name (sig->digest_algo),
+                  *pkstrbuf?", key algorithm ":"",
+                  pkstrbuf);
 
       if (rc)
         g10_errors_seen = 1;

commit e73edfb1759d05121ea66f67c775e763bf47d737
Author: Werner Koch <wk at gnupg.org>
Date:   Wed May 7 14:36:34 2014 +0200

    gpg: Fix memleak in signature verification of bogus keys.
    
    * g10/mainproc.c (check_sig_and_print): Factor common code out to ...
    (print_good_bad_signature): here.
    --
    
    P was not released if the key had no user id.

diff --git a/g10/mainproc.c b/g10/mainproc.c
index 20a799f..d4a0549 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1528,12 +1528,42 @@ pka_uri_from_sig (PKT_signature *sig)
 }
 
 
+static void
+print_good_bad_signature (int statno, const char *keyid_str, kbnode_t un,
+                          PKT_signature *sig, int rc)
+{
+  char *p;
+
+  write_status_text_and_buffer (statno, keyid_str,
+                                un? un->pkt->pkt.user_id->name:"[?]",
+                                un? un->pkt->pkt.user_id->len:3,
+                                -1);
+
+  if (un)
+    p = utf8_to_native (un->pkt->pkt.user_id->name,
+                        un->pkt->pkt.user_id->len, 0);
+  else
+    p = xstrdup ("[?]");
+
+  if (rc)
+    log_info (_("BAD signature from \"%s\""), p);
+  else if (sig->flags.expired)
+    log_info (_("Expired signature from \"%s\""), p);
+  else
+    log_info (_("Good signature from \"%s\""), p);
+
+  xfree (p);
+}
+
+
 static int
 check_sig_and_print (CTX c, KBNODE node)
 {
   PKT_signature *sig = node->pkt->pkt.signature;
   const char *astr;
-  int rc, is_expkey=0, is_revkey=0;
+  int rc;
+  int is_expkey = 0;
+  int is_revkey = 0;
 
   if (opt.skip_verify)
     {
@@ -1663,7 +1693,7 @@ check_sig_and_print (CTX c, KBNODE node)
               asctimestamp(sig->timestamp), astr? astr: "?",
               keystr(sig->keyid));
 
-  rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
+  rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey );
 
   /* If the key isn't found, check for a preferred keyserver */
 
@@ -1778,7 +1808,6 @@ check_sig_and_print (CTX c, KBNODE node)
       /* Find and print the primary user ID.  */
       for (un=keyblock; un; un = un->next)
         {
-          char *p;
           int valid;
 
           if (un->pkt->pkttype==PKT_PUBLIC_KEY)
@@ -1807,24 +1836,10 @@ check_sig_and_print (CTX c, KBNODE node)
           valid = get_validity (pk, un->pkt->pkt.user_id);
 
           keyid_str[17] = 0; /* cut off the "[uncertain]" part */
-          write_status_text_and_buffer (statno, keyid_str,
-                                        un->pkt->pkt.user_id->name,
-                                        un->pkt->pkt.user_id->len,
-                                        -1);
-
-          p = utf8_to_native (un->pkt->pkt.user_id->name,
-                              un->pkt->pkt.user_id->len, 0);
-
-          if (rc)
-            log_info (_("BAD signature from \"%s\""), p);
-          else if (sig->flags.expired)
-            log_info (_("Expired signature from \"%s\""), p);
-          else
-            log_info (_("Good signature from \"%s\""), p);
 
-          xfree(p);
+          print_good_bad_signature (statno, keyid_str, un, sig, rc);
 
-          if (opt.verify_options&VERIFY_SHOW_UID_VALIDITY)
+          if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY))
             log_printf (" [%s]\n",trust_value_to_string(valid));
           else
             log_printf ("\n");
@@ -1833,8 +1848,6 @@ check_sig_and_print (CTX c, KBNODE node)
 
       if (!count)  /* Just in case that we have no valid textual userid */
         {
-          char *p;
-
           /* Try for an invalid textual userid */
           for (un=keyblock; un; un = un->next)
             {
@@ -1856,23 +1869,8 @@ check_sig_and_print (CTX c, KBNODE node)
           if (opt.trust_model==TM_ALWAYS || !un)
             keyid_str[17] = 0; /* cut off the "[uncertain]" part */
 
-          write_status_text_and_buffer (statno, keyid_str,
-                                        un? un->pkt->pkt.user_id->name:"[?]",
-                                        un? un->pkt->pkt.user_id->len:3,
-                                        -1 );
-
-          if (un)
-            p= utf8_to_native (un->pkt->pkt.user_id->name,
-                               un->pkt->pkt.user_id->len, 0);
-          else
-            p = xstrdup ("[?]");
+          print_good_bad_signature (statno, keyid_str, un, sig, rc);
 
-          if (rc)
-            log_info (_("BAD signature from \"%s\""), p);
-          else if (sig->flags.expired)
-            log_info (_("Expired signature from \"%s\""), p);
-          else
-            log_info (_("Good signature from \"%s\""), p);
           if (opt.trust_model != TM_ALWAYS && un)
             log_printf (" %s",_("[uncertain]") );
           log_printf ("\n");

commit e5279c85a04084a2277acb224bd4ca3026dcafd4
Author: Werner Koch <wk at gnupg.org>
Date:   Wed May 7 14:08:16 2014 +0200

    gpg: Fix indendation of check_sig_and_print.
    
    --

diff --git a/g10/mainproc.c b/g10/mainproc.c
index f830eee..20a799f 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1,7 +1,7 @@
 /* mainproc.c - handle packets
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
  *               2008, 2009 Free Software Foundation, Inc.
- * Copyright (C) 2013 Werner Koch
+ * Copyright (C) 2013, 2014 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -1529,7 +1529,7 @@ pka_uri_from_sig (PKT_signature *sig)
 
 
 static int
-check_sig_and_print( CTX c, KBNODE node )
+check_sig_and_print (CTX c, KBNODE node)
 {
   PKT_signature *sig = node->pkt->pkt.signature;
   const char *astr;
@@ -1649,390 +1649,405 @@ check_sig_and_print( CTX c, KBNODE node )
         log_error(_("can't handle this ambiguous signature data\n"));
         return 0;
       }
-
   }
 
-  /* (Indendation below not yet changed to GNU style.) */
+  astr = openpgp_pk_algo_name ( sig->pubkey_algo );
+  if (keystrlen () > 8)
+    {
+      log_info (_("Signature made %s\n"), asctimestamp(sig->timestamp));
+      log_info (_("               using %s key %s\n"),
+                astr? astr: "?",keystr(sig->keyid));
+    }
+  else
+    log_info (_("Signature made %s using %s key ID %s\n"),
+              asctimestamp(sig->timestamp), astr? astr: "?",
+              keystr(sig->keyid));
 
-    astr = openpgp_pk_algo_name ( sig->pubkey_algo );
-    if(keystrlen()>8)
-      {
-	log_info(_("Signature made %s\n"),asctimestamp(sig->timestamp));
-	log_info(_("               using %s key %s\n"),
-		 astr? astr: "?",keystr(sig->keyid));
-      }
-    else
-      log_info(_("Signature made %s using %s key ID %s\n"),
-	       asctimestamp(sig->timestamp), astr? astr: "?",
-	       keystr(sig->keyid));
+  rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
 
-    rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
+  /* If the key isn't found, check for a preferred keyserver */
 
-    /* If the key isn't found, check for a preferred keyserver */
+  if (gpg_err_code (rc) == G10ERR_NO_PUBKEY && sig->flags.pref_ks)
+    {
+      const byte *p;
+      int seq = 0;
+      size_t n;
 
-    if(rc==G10ERR_NO_PUBKEY && sig->flags.pref_ks)
-      {
-	const byte *p;
-	int seq=0;
-	size_t n;
+      while ((p=enum_sig_subpkt (sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL)))
+        {
+          /* According to my favorite copy editor, in English grammar,
+             you say "at" if the key is located on a web page, but
+             "from" if it is located on a keyserver.  I'm not going to
+             even try to make two strings here :) */
+          log_info(_("Key available at: ") );
+          print_utf8_buffer (log_get_stream(), p, n);
+          log_printf ("\n");
+
+          if (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE
+              && opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL)
+            {
+              struct keyserver_spec *spec;
 
-	while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL)))
-	  {
-	    /* According to my favorite copy editor, in English
-	       grammar, you say "at" if the key is located on a web
-	       page, but "from" if it is located on a keyserver.  I'm
-	       not going to even try to make two strings here :) */
-	    log_info(_("Key available at: ") );
-	    print_utf8_buffer (log_get_stream(), p, n);
-	    log_printf ("\n");
-
-	    if(opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE
-	       && opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL)
-	      {
-		struct keyserver_spec *spec;
+              spec = parse_preferred_keyserver (sig);
+              if (spec)
+                {
+                  int res;
 
-		spec=parse_preferred_keyserver(sig);
-		if(spec)
-		  {
-		    int res;
+                  glo_ctrl.in_auto_key_retrieve++;
+                  res = keyserver_import_keyid (c->ctrl, sig->keyid,spec);
+                  glo_ctrl.in_auto_key_retrieve--;
+                  if (!res)
+                    rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
+                  free_keyserver_spec (spec);
 
-		    glo_ctrl.in_auto_key_retrieve++;
-		    res = keyserver_import_keyid (c->ctrl, sig->keyid,spec);
-		    glo_ctrl.in_auto_key_retrieve--;
-		    if(!res)
-		      rc=do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
-		    free_keyserver_spec(spec);
-
-		    if(!rc)
-		      break;
-		  }
-	      }
-	  }
-      }
+                  if (!rc)
+                    break;
+                }
+            }
+        }
+    }
 
-    /* If the preferred keyserver thing above didn't work, our second
-       try is to use the URI from a DNS PKA record. */
-    if ( rc == G10ERR_NO_PUBKEY
-	 && opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE
-         && opt.keyserver_options.options&KEYSERVER_HONOR_PKA_RECORD)
-      {
-        const char *uri = pka_uri_from_sig (sig);
+  /* If the preferred keyserver thing above didn't work, our second
+     try is to use the URI from a DNS PKA record. */
+  if (gpg_err_code (rc) == G10ERR_NO_PUBKEY
+      && (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
+      && (opt.keyserver_options.options & KEYSERVER_HONOR_PKA_RECORD))
+    {
+      const char *uri = pka_uri_from_sig (sig);
 
-        if (uri)
-          {
-            /* FIXME: We might want to locate the key using the
-               fingerprint instead of the keyid. */
-            int res;
-            struct keyserver_spec *spec;
+      if (uri)
+        {
+          /* FIXME: We might want to locate the key using the
+             fingerprint instead of the keyid. */
+          int res;
+          struct keyserver_spec *spec;
 
-            spec = parse_keyserver_uri (uri, 1, NULL, 0);
-            if (spec)
-              {
-                glo_ctrl.in_auto_key_retrieve++;
-                res = keyserver_import_keyid (c->ctrl, sig->keyid, spec);
+          spec = parse_keyserver_uri (uri, 1, NULL, 0);
+          if (spec)
+            {
+              glo_ctrl.in_auto_key_retrieve++;
+              res = keyserver_import_keyid (c->ctrl, sig->keyid, spec);
                 glo_ctrl.in_auto_key_retrieve--;
                 free_keyserver_spec (spec);
                 if (!res)
-                  rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
-              }
-          }
-      }
+                  rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey );
+            }
+        }
+    }
 
-    /* If the preferred keyserver thing above didn't work and we got
+  /* If the preferred keyserver thing above didn't work and we got
        no information from the DNS PKA, this is a third try. */
 
-    if( rc == G10ERR_NO_PUBKEY && opt.keyserver
-	&& opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
-      {
-	int res;
+  if (gpg_err_code (rc) == G10ERR_NO_PUBKEY
+      && opt.keyserver
+      && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE))
+    {
+      int res;
 
-	glo_ctrl.in_auto_key_retrieve++;
-	res=keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver );
-	glo_ctrl.in_auto_key_retrieve--;
-	if(!res)
-	  rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
-      }
+      glo_ctrl.in_auto_key_retrieve++;
+      res=keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver );
+      glo_ctrl.in_auto_key_retrieve--;
+      if (!res)
+        rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey );
+    }
 
-    if( !rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE ) {
-	KBNODE un, keyblock;
-	int count=0, statno;
-        char keyid_str[50];
-	PKT_public_key *pk=NULL;
-
-	if(rc)
-	  statno=STATUS_BADSIG;
-	else if(sig->flags.expired)
-	  statno=STATUS_EXPSIG;
-	else if(is_expkey)
-	  statno=STATUS_EXPKEYSIG;
-	else if(is_revkey)
-	  statno=STATUS_REVKEYSIG;
-	else
-	  statno=STATUS_GOODSIG;
+  if (!rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE)
+    {
+      kbnode_t un, keyblock;
+      int count = 0;
+      int statno;
+      char keyid_str[50];
+      PKT_public_key *pk = NULL;
+
+      if (rc)
+        statno = STATUS_BADSIG;
+      else if (sig->flags.expired)
+        statno = STATUS_EXPSIG;
+      else if (is_expkey)
+        statno = STATUS_EXPKEYSIG;
+      else if(is_revkey)
+        statno = STATUS_REVKEYSIG;
+      else
+        statno = STATUS_GOODSIG;
+
+      keyblock = get_pubkeyblock (sig->keyid);
+
+      snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX [uncertain] ",
+                (ulong)sig->keyid[0], (ulong)sig->keyid[1]);
+
+      /* Find and print the primary user ID.  */
+      for (un=keyblock; un; un = un->next)
+        {
+          char *p;
+          int valid;
 
-	keyblock = get_pubkeyblock( sig->keyid );
+          if (un->pkt->pkttype==PKT_PUBLIC_KEY)
+            {
+              pk=un->pkt->pkt.public_key;
+              continue;
+            }
+          if (un->pkt->pkttype != PKT_USER_ID)
+            continue;
+          if (!un->pkt->pkt.user_id->created)
+            continue;
+          if (un->pkt->pkt.user_id->is_revoked)
+            continue;
+          if (un->pkt->pkt.user_id->is_expired)
+            continue;
+          if (!un->pkt->pkt.user_id->is_primary)
+            continue;
+          /* We want the textual primary user ID here */
+          if (un->pkt->pkt.user_id->attrib_data)
+            continue;
 
-        sprintf (keyid_str, "%08lX%08lX [uncertain] ",
-                 (ulong)sig->keyid[0], (ulong)sig->keyid[1]);
+          assert (pk);
 
-        /* find and print the primary user ID */
-	for( un=keyblock; un; un = un->next ) {
-	    char *p;
-	    int valid;
-	    if(un->pkt->pkttype==PKT_PUBLIC_KEY)
-	      {
-	        pk=un->pkt->pkt.public_key;
-		continue;
-	      }
-	    if( un->pkt->pkttype != PKT_USER_ID )
-		continue;
-	    if ( !un->pkt->pkt.user_id->created )
-	        continue;
-            if ( un->pkt->pkt.user_id->is_revoked )
-                continue;
-            if ( un->pkt->pkt.user_id->is_expired )
-                continue;
-	    if ( !un->pkt->pkt.user_id->is_primary )
-	        continue;
-	    /* We want the textual primary user ID here */
-	    if ( un->pkt->pkt.user_id->attrib_data )
-	        continue;
+          /* Get it before we print anything to avoid interrupting the
+             output with the "please do a --check-trustdb" line. */
+          valid = get_validity (pk, un->pkt->pkt.user_id);
 
-	    assert(pk);
+          keyid_str[17] = 0; /* cut off the "[uncertain]" part */
+          write_status_text_and_buffer (statno, keyid_str,
+                                        un->pkt->pkt.user_id->name,
+                                        un->pkt->pkt.user_id->len,
+                                        -1);
 
-	    /* Get it before we print anything to avoid interrupting
-	       the output with the "please do a --check-trustdb"
-	       line. */
-	    valid=get_validity(pk,un->pkt->pkt.user_id);
+          p = utf8_to_native (un->pkt->pkt.user_id->name,
+                              un->pkt->pkt.user_id->len, 0);
 
-            keyid_str[17] = 0; /* cut off the "[uncertain]" part */
-            write_status_text_and_buffer (statno, keyid_str,
-                                          un->pkt->pkt.user_id->name,
-                                          un->pkt->pkt.user_id->len,
-                                          -1 );
-
-	    p=utf8_to_native(un->pkt->pkt.user_id->name,
-			     un->pkt->pkt.user_id->len,0);
-
-	    if(rc)
-	      log_info(_("BAD signature from \"%s\""),p);
-	    else if(sig->flags.expired)
-	      log_info(_("Expired signature from \"%s\""),p);
-	    else
-	      log_info(_("Good signature from \"%s\""),p);
+          if (rc)
+            log_info (_("BAD signature from \"%s\""), p);
+          else if (sig->flags.expired)
+            log_info (_("Expired signature from \"%s\""), p);
+          else
+            log_info (_("Good signature from \"%s\""), p);
 
-	    xfree(p);
+          xfree(p);
 
-	    if(opt.verify_options&VERIFY_SHOW_UID_VALIDITY)
-	      log_printf (" [%s]\n",trust_value_to_string(valid));
-	    else
-	      log_printf ("\n");
-            count++;
+          if (opt.verify_options&VERIFY_SHOW_UID_VALIDITY)
+            log_printf (" [%s]\n",trust_value_to_string(valid));
+          else
+            log_printf ("\n");
+          count++;
 	}
-	if( !count ) {	/* just in case that we have no valid textual
-                           userid */
-	    char *p;
 
-	    /* Try for an invalid textual userid */
-            for( un=keyblock; un; un = un->next ) {
-                if( un->pkt->pkttype == PKT_USER_ID &&
-		    !un->pkt->pkt.user_id->attrib_data )
-                    break;
+      if (!count)  /* Just in case that we have no valid textual userid */
+        {
+          char *p;
+
+          /* Try for an invalid textual userid */
+          for (un=keyblock; un; un = un->next)
+            {
+              if (un->pkt->pkttype == PKT_USER_ID
+                  && !un->pkt->pkt.user_id->attrib_data)
+                break;
             }
 
-	    /* Try for any userid at all */
-	    if(!un) {
-	        for( un=keyblock; un; un = un->next ) {
-                    if( un->pkt->pkttype == PKT_USER_ID )
-                        break;
+          /* Try for any userid at all */
+          if (!un)
+            {
+              for (un=keyblock; un; un = un->next)
+                {
+                  if (un->pkt->pkttype == PKT_USER_ID)
+                    break;
 		}
 	    }
 
-            if (opt.trust_model==TM_ALWAYS || !un)
-                keyid_str[17] = 0; /* cut off the "[uncertain]" part */
-
-            write_status_text_and_buffer (statno, keyid_str,
-                                          un? un->pkt->pkt.user_id->name:"[?]",
-                                          un? un->pkt->pkt.user_id->len:3,
-                                          -1 );
-
-	    if(un)
-	      p=utf8_to_native(un->pkt->pkt.user_id->name,
-                               un->pkt->pkt.user_id->len,0);
-	    else
-	      p=xstrdup("[?]");
+          if (opt.trust_model==TM_ALWAYS || !un)
+            keyid_str[17] = 0; /* cut off the "[uncertain]" part */
 
-	    if(rc)
-	      log_info(_("BAD signature from \"%s\""),p);
-	    else if(sig->flags.expired)
-	      log_info(_("Expired signature from \"%s\""),p);
-	    else
-	      log_info(_("Good signature from \"%s\""),p);
-            if (opt.trust_model!=TM_ALWAYS && un)
-              log_printf (" %s",_("[uncertain]") );
-	    log_printf ("\n");
+          write_status_text_and_buffer (statno, keyid_str,
+                                        un? un->pkt->pkt.user_id->name:"[?]",
+                                        un? un->pkt->pkt.user_id->len:3,
+                                        -1 );
+
+          if (un)
+            p= utf8_to_native (un->pkt->pkt.user_id->name,
+                               un->pkt->pkt.user_id->len, 0);
+          else
+            p = xstrdup ("[?]");
+
+          if (rc)
+            log_info (_("BAD signature from \"%s\""), p);
+          else if (sig->flags.expired)
+            log_info (_("Expired signature from \"%s\""), p);
+          else
+            log_info (_("Good signature from \"%s\""), p);
+          if (opt.trust_model != TM_ALWAYS && un)
+            log_printf (" %s",_("[uncertain]") );
+          log_printf ("\n");
 	}
 
-        /* If we have a good signature and already printed
-         * the primary user ID, print all the other user IDs */
-        if ( count && !rc
-             && !(opt.verify_options&VERIFY_SHOW_PRIMARY_UID_ONLY)) {
-	    char *p;
-            for( un=keyblock; un; un = un->next ) {
-                if( un->pkt->pkttype != PKT_USER_ID )
-                    continue;
-                if((un->pkt->pkt.user_id->is_revoked
-		    || un->pkt->pkt.user_id->is_expired)
-		   && !(opt.verify_options&VERIFY_SHOW_UNUSABLE_UIDS))
-		  continue;
-		/* Only skip textual primaries */
-                if ( un->pkt->pkt.user_id->is_primary &&
-		     !un->pkt->pkt.user_id->attrib_data )
-		    continue;
-
-		if(un->pkt->pkt.user_id->attrib_data)
-		  {
-		    dump_attribs (un->pkt->pkt.user_id, pk);
+      /* If we have a good signature and already printed
+       * the primary user ID, print all the other user IDs */
+      if (count
+          && !rc
+          && !(opt.verify_options & VERIFY_SHOW_PRIMARY_UID_ONLY))
+        {
+          char *p;
+          for( un=keyblock; un; un = un->next)
+            {
+              if (un->pkt->pkttype != PKT_USER_ID)
+                continue;
+              if ((un->pkt->pkt.user_id->is_revoked
+                   || un->pkt->pkt.user_id->is_expired)
+                  && !(opt.verify_options & VERIFY_SHOW_UNUSABLE_UIDS))
+                continue;
+              /* Only skip textual primaries */
+              if (un->pkt->pkt.user_id->is_primary
+                  && !un->pkt->pkt.user_id->attrib_data )
+                continue;
 
-		    if(opt.verify_options&VERIFY_SHOW_PHOTOS)
-		      show_photos(un->pkt->pkt.user_id->attribs,
-				  un->pkt->pkt.user_id->numattribs,
-				  pk ,un->pkt->pkt.user_id);
-		  }
+              if (un->pkt->pkt.user_id->attrib_data)
+                {
+                  dump_attribs (un->pkt->pkt.user_id, pk);
 
-		p=utf8_to_native(un->pkt->pkt.user_id->name,
-				 un->pkt->pkt.user_id->len,0);
-		log_info(_("                aka \"%s\""),p);
-		xfree(p);
+                  if (opt.verify_options&VERIFY_SHOW_PHOTOS)
+                    show_photos (un->pkt->pkt.user_id->attribs,
+                                 un->pkt->pkt.user_id->numattribs,
+                                 pk ,un->pkt->pkt.user_id);
+                }
 
-		if(opt.verify_options&VERIFY_SHOW_UID_VALIDITY)
-		  {
-		    const char *valid;
-		    if(un->pkt->pkt.user_id->is_revoked)
-		      valid=_("revoked");
-		    else if(un->pkt->pkt.user_id->is_expired)
-		      valid=_("expired");
-		    else
-		      valid=trust_value_to_string(get_validity(pk,
-							       un->pkt->
-							       pkt.user_id));
-		    log_printf (" [%s]\n",valid);
-		  }
-		else
-		  log_printf ("\n");
+              p = utf8_to_native (un->pkt->pkt.user_id->name,
+				  un->pkt->pkt.user_id->len, 0);
+              log_info (_("                aka \"%s\""), p);
+              xfree (p);
+
+              if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY))
+                {
+                  const char *valid;
+
+                  if (un->pkt->pkt.user_id->is_revoked)
+                    valid = _("revoked");
+                  else if (un->pkt->pkt.user_id->is_expired)
+                    valid = _("expired");
+                  else
+                    valid = (trust_value_to_string
+                             (get_validity (pk, un->pkt->pkt.user_id)));
+                  log_printf (" [%s]\n",valid);
+                }
+              else
+                log_printf ("\n");
             }
 	}
-	release_kbnode( keyblock );
+      release_kbnode( keyblock );
 
-	if( !rc )
-	  {
-	    if(opt.verify_options&VERIFY_SHOW_POLICY_URLS)
-	      show_policy_url(sig,0,1);
-	    else
-	      show_policy_url(sig,0,2);
-
-	    if(opt.verify_options&VERIFY_SHOW_KEYSERVER_URLS)
-	      show_keyserver_url(sig,0,1);
-	    else
-	      show_keyserver_url(sig,0,2);
+      if (!rc)
+        {
+          if ((opt.verify_options & VERIFY_SHOW_POLICY_URLS))
+            show_policy_url (sig, 0, 1);
+          else
+            show_policy_url (sig, 0, 2);
+
+          if ((opt.verify_options & VERIFY_SHOW_KEYSERVER_URLS))
+            show_keyserver_url (sig, 0, 1);
+          else
+            show_keyserver_url (sig, 0, 2);
+
+          if ((opt.verify_options & VERIFY_SHOW_NOTATIONS))
+            show_notation
+              (sig, 0, 1,
+               (((opt.verify_options&VERIFY_SHOW_STD_NOTATIONS)?1:0)
+                + ((opt.verify_options&VERIFY_SHOW_USER_NOTATIONS)?2:0)));
+          else
+            show_notation (sig, 0, 2, 0);
+        }
 
-	    if(opt.verify_options&VERIFY_SHOW_NOTATIONS)
-	      show_notation(sig,0,1,
-		        ((opt.verify_options&VERIFY_SHOW_STD_NOTATIONS)?1:0)+
-			((opt.verify_options&VERIFY_SHOW_USER_NOTATIONS)?2:0));
-	    else
-	      show_notation(sig,0,2,0);
-	  }
+      if (!rc && is_status_enabled ())
+        {
+          /* Print a status response with the fingerprint. */
+          PKT_public_key *vpk = xmalloc_clear (sizeof *vpk);
 
-	if( !rc && is_status_enabled() ) {
-	    /* print a status response with the fingerprint */
-	    PKT_public_key *vpk = xmalloc_clear( sizeof *vpk );
-
-	    if( !get_pubkey( vpk, sig->keyid ) ) {
-		byte array[MAX_FINGERPRINT_LEN], *p;
-		char buf[MAX_FINGERPRINT_LEN*4+90], *bufp;
-		size_t i, n;
-
-                bufp = buf;
-		fingerprint_from_pk( vpk, array, &n );
-		p = array;
-		for(i=0; i < n ; i++, p++, bufp += 2)
-                    sprintf(bufp, "%02X", *p );
-		/* TODO: Replace the reserved '0' in the field below
-		   with bits for status flags (policy url, notation,
-		   etc.).  Remember to make the buffer larger to
-		   match! */
-		sprintf(bufp, " %s %lu %lu %d 0 %d %d %02X ",
-                        strtimestamp( sig->timestamp ),
-                        (ulong)sig->timestamp,(ulong)sig->expiredate,
-			sig->version,sig->pubkey_algo,sig->digest_algo,
-			sig->sig_class);
-                bufp = bufp + strlen (bufp);
-                if (!vpk->flags.primary) {
-                   u32 akid[2];
-
-                   akid[0] = vpk->main_keyid[0];
-                   akid[1] = vpk->main_keyid[1];
-                   free_public_key (vpk);
-                   vpk = xmalloc_clear( sizeof *vpk );
-                   if (get_pubkey (vpk, akid)) {
-                     /* impossible error, we simply return a zeroed out fpr */
-                     n = MAX_FINGERPRINT_LEN < 20? MAX_FINGERPRINT_LEN : 20;
-                     memset (array, 0, n);
-                   }
-                   else
-                     fingerprint_from_pk( vpk, array, &n );
+          if (!get_pubkey (vpk, sig->keyid))
+            {
+              byte array[MAX_FINGERPRINT_LEN], *p;
+              char buf[MAX_FINGERPRINT_LEN*4+90], *bufp;
+              size_t i, n;
+
+              bufp = buf;
+              fingerprint_from_pk (vpk, array, &n);
+              p = array;
+              for(i=0; i < n ; i++, p++, bufp += 2)
+                sprintf (bufp, "%02X", *p );
+              /* TODO: Replace the reserved '0' in the field below
+                 with bits for status flags (policy url, notation,
+                 etc.).  Remember to make the buffer larger to match! */
+              sprintf (bufp, " %s %lu %lu %d 0 %d %d %02X ",
+                       strtimestamp( sig->timestamp ),
+                       (ulong)sig->timestamp,(ulong)sig->expiredate,
+                       sig->version,sig->pubkey_algo,sig->digest_algo,
+                       sig->sig_class);
+              bufp = bufp + strlen (bufp);
+              if (!vpk->flags.primary)
+                {
+                  u32 akid[2];
+
+                  akid[0] = vpk->main_keyid[0];
+                  akid[1] = vpk->main_keyid[1];
+                  free_public_key (vpk);
+                  vpk = xmalloc_clear (sizeof *vpk);
+                  if (get_pubkey (vpk, akid))
+                    {
+                      /* Impossible error, we simply return a zeroed out fpr */
+                      n = MAX_FINGERPRINT_LEN < 20? MAX_FINGERPRINT_LEN : 20;
+                      memset (array, 0, n);
+                    }
+                  else
+                    fingerprint_from_pk( vpk, array, &n );
                 }
-		p = array;
-		for(i=0; i < n ; i++, p++, bufp += 2)
-                    sprintf(bufp, "%02X", *p );
-		write_status_text( STATUS_VALIDSIG, buf );
+              p = array;
+              for (i=0; i < n ; i++, p++, bufp += 2)
+                sprintf(bufp, "%02X", *p );
+              write_status_text (STATUS_VALIDSIG, buf);
 	    }
-	    free_public_key( vpk );
+          free_public_key (vpk);
 	}
 
-	if (!rc)
-          {
-	    if(opt.verify_options&VERIFY_PKA_LOOKUPS)
-	      pka_uri_from_sig (sig); /* Make sure PKA info is available. */
-	    rc = check_signatures_trust( sig );
-          }
+      if (!rc)
+        {
+          if ((opt.verify_options & VERIFY_PKA_LOOKUPS))
+            pka_uri_from_sig (sig); /* Make sure PKA info is available. */
+          rc = check_signatures_trust (sig);
+        }
 
-	if(sig->flags.expired)
-	  {
-	    log_info(_("Signature expired %s\n"),
-		     asctimestamp(sig->expiredate));
-	    rc=G10ERR_GENERAL; /* need a better error here? */
-	  }
-	else if(sig->expiredate)
-	  log_info(_("Signature expires %s\n"),asctimestamp(sig->expiredate));
-
-	if(opt.verbose)
-	  log_info(_("%s signature, digest algorithm %s\n"),
-		   sig->sig_class==0x00?_("binary"):
-		   sig->sig_class==0x01?_("textmode"):_("unknown"),
-		   gcry_md_algo_name (sig->digest_algo));
-
-	if( rc )
-	    g10_errors_seen = 1;
-	if( opt.batch && rc )
-	    g10_exit(1);
+      if (sig->flags.expired)
+        {
+          log_info (_("Signature expired %s\n"), asctimestamp(sig->expiredate));
+          rc = G10ERR_GENERAL; /* need a better error here? */
+        }
+      else if (sig->expiredate)
+        log_info (_("Signature expires %s\n"), asctimestamp(sig->expiredate));
+
+      if (opt.verbose)
+        log_info (_("%s signature, digest algorithm %s\n"),
+                  sig->sig_class==0x00?_("binary"):
+                  sig->sig_class==0x01?_("textmode"):_("unknown"),
+                  gcry_md_algo_name (sig->digest_algo));
+
+      if (rc)
+        g10_errors_seen = 1;
+      if (opt.batch && rc)
+        g10_exit (1);
     }
-    else {
-	char buf[50];
-	sprintf(buf, "%08lX%08lX %d %d %02x %lu %d",
-		     (ulong)sig->keyid[0], (ulong)sig->keyid[1],
-		     sig->pubkey_algo, sig->digest_algo,
-		     sig->sig_class, (ulong)sig->timestamp, rc );
-	write_status_text( STATUS_ERRSIG, buf );
-	if( rc == G10ERR_NO_PUBKEY ) {
-	    buf[16] = 0;
-	    write_status_text( STATUS_NO_PUBKEY, buf );
+  else
+    {
+      char buf[50];
+
+      snprintf (buf, sizeof buf, "%08lX%08lX %d %d %02x %lu %d",
+                (ulong)sig->keyid[0], (ulong)sig->keyid[1],
+                sig->pubkey_algo, sig->digest_algo,
+                sig->sig_class, (ulong)sig->timestamp, rc);
+      write_status_text (STATUS_ERRSIG, buf);
+      if (gpg_err_code (rc) == G10ERR_NO_PUBKEY)
+        {
+          buf[16] = 0;
+          write_status_text (STATUS_NO_PUBKEY, buf);
 	}
-	if( rc != G10ERR_NOT_PROCESSED )
-	    log_error(_("Can't check signature: %s\n"), g10_errstr(rc) );
+      if (gpg_err_code (rc) != G10ERR_NOT_PROCESSED)
+        log_error (_("Can't check signature: %s\n"), g10_errstr(rc));
     }
-    return rc;
+
+  return rc;
 }
 
 

commit 09055aa0f7993aaf4dcffdd80d8192945ae6080a
Author: Werner Koch <wk at gnupg.org>
Date:   Wed May 7 13:39:28 2014 +0200

    gpg: Mark experimental algorithms in the key listing.
    
    * g10/keylist.c (list_keyblock_print): Remove duplicate curve name.
    Print a note for experimental algorithms.
    * g10/misc.c (print_pubkey_algo_note): Fix warning message.

diff --git a/g10/keylist.c b/g10/keylist.c
index 71f72e2..1ecfce9 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -1,6 +1,7 @@
 /* keylist.c - Print information about OpenPGP keys
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
  *               2008, 2010, 2012 Free Software Foundation, Inc.
+ * Copyright (C) 2013, 2014  Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -822,18 +823,6 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
               pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
               keystr_from_pk (pk), datestr_from_pk (pk));
 
-  if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
-      || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
-      || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
-    {
-      char *curve = openpgp_oid_to_str (pk->pkey[0]);
-      const char *name = openpgp_oid_to_curve (curve);
-      if (!*name || *name == '?')
-        name = curve;
-      es_fprintf (es_stdout, " %s", name);
-      xfree (curve);
-    }
-
   if (pk->flags.revoked)
     {
       es_fprintf (es_stdout, " [");
@@ -863,6 +852,9 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
     }
 #endif
 
+  if (pk->pubkey_algo >= 100)
+    es_fprintf (es_stdout, " [experimental algorithm %d]", pk->pubkey_algo);
+
   es_fprintf (es_stdout, "\n");
 
   if (fpr)
diff --git a/g10/misc.c b/g10/misc.c
index 77928aa..54ddad2 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -299,10 +299,10 @@ print_pubkey_algo_note (pubkey_algo_t algo)
 	{
 	  warn=1;
 	  log_info (_("WARNING: using experimental public key algorithm %s\n"),
-		    openpgp_cipher_algo_name (algo));
+		    openpgp_pk_algo_name (algo));
 	}
     }
-  else if (algo == 20)
+  else if (algo == PUBKEY_ALGO_ELGAMAL)
     {
       log_info (_("WARNING: Elgamal sign+encrypt keys are deprecated\n"));
     }

commit 8fee6c1ce6d116fe7909dbe1184d95bc91305484
Author: Werner Koch <wk at gnupg.org>
Date:   Wed May 7 13:16:32 2014 +0200

    gpg: Finish experimental support for Ed25519.
    
    * agent/cvt-openpgp.c (try_do_unprotect_arg_s): Add field "curve".
    (get_keygrip): Add and use arg CURVE.
    (convert_secret_key): Ditto.
    (convert_transfer_key): Ditto.
    (get_npkey_nskey): New.
    (prepare_unprotect): Replace gcrypt functions by
    get_npkey_nskey.  Allow opaque MPIs.
    (do_unprotect): Use CURVE instead of parameters.
    (convert_from_openpgp_main): Ditto.
    (convert_to_openpgp):  Simplify.
    * g10/import.c (one_mpi_from_pkey): Remove.
    (transfer_secret_keys): Rewrite to use the curve instead of the
    parameters.
    * g10/parse-packet.c (parse_key): Mark protected MPIs with USER1 flag.
    
    * common/openpgp-oid.c (openpgp_curve_to_oid): Allow the use of
     "NIST P-256" et al.
    * g10/keygen.c (ask_curve): Add arg ALGO.
    (generate_keypair): Rewrite the ECC key logic.
    
    * tests/openpgp/ecc.test: Provide the "ecc" passphrase.

diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c
index ef34463..28f0380 100644
--- a/agent/cvt-openpgp.c
+++ b/agent/cvt-openpgp.c
@@ -36,6 +36,7 @@ struct try_do_unprotect_arg_s
   int  is_v4;
   int  is_protected;
   int  pubkey_algo;
+  const char *curve;
   int  protect_algo;
   char *iv;
   int  ivlen;
@@ -54,7 +55,8 @@ struct try_do_unprotect_arg_s
 
 /* Compute the keygrip from the public key and store it at GRIP.  */
 static gpg_error_t
-get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip)
+get_keygrip (int pubkey_algo, const char *curve, gcry_mpi_t *pkey,
+             unsigned char *grip)
 {
   gpg_error_t err;
   gcry_sexp_t s_pkey = NULL;
@@ -80,9 +82,8 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip)
 
     case GCRY_PK_ECC:
       err = gcry_sexp_build (&s_pkey, NULL,
-                             "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))",
-                             pkey[0], pkey[1], pkey[2], pkey[3], pkey[4],
-                             pkey[5]);
+                             "(public-key(ecc(curve %s)(q%m)))",
+                             curve, pkey[0]);
       break;
 
     default:
@@ -102,7 +103,8 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip)
    parameters into our s-expression based format.  Note that
    PUBKEY_ALGO has an gcrypt algorithm number. */
 static gpg_error_t
-convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
+convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
+                    const char *curve)
 {
   gpg_error_t err;
   gcry_sexp_t s_skey = NULL;
@@ -135,11 +137,12 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
       break;
 
     case GCRY_PK_ECC:
-      err = gcry_sexp_build (&s_skey, NULL,
-                             "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)"
-                             "(d%m)))",
-                             skey[0], skey[1], skey[2], skey[3], skey[4],
-                             skey[5], skey[6]);
+      if (!curve)
+        err = gpg_error (GPG_ERR_BAD_SECKEY);
+      else
+        err = gcry_sexp_build (&s_skey, NULL,
+                               "(private-key(ecc(curve%s)(q%m)(d%m)))",
+                               curve, skey[0], skey[1]);
       break;
 
     default:
@@ -160,7 +163,7 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
    mode.  Note that PUBKEY_ALGO has an gcrypt algorithm number. */
 static gpg_error_t
 convert_transfer_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
-                      gcry_sexp_t transfer_key)
+                      const char *curve, gcry_sexp_t transfer_key)
 {
   gpg_error_t err;
   gcry_sexp_t s_skey = NULL;
@@ -197,9 +200,9 @@ convert_transfer_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
     case GCRY_PK_ECC:
       err = gcry_sexp_build
         (&s_skey, NULL,
-         "(protected-private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)"
+         "(protected-private-key(ecc(curve%s)(q%m)"
          "(protected openpgp-native%S)))",
-         skey[0], skey[1], skey[2], skey[3], skey[4], skey[5], transfer_key);
+         curve, skey[0], transfer_key);
       break;
 
     default:
@@ -254,6 +257,22 @@ checksum (const unsigned char *p, unsigned int n)
 }
 
 
+/* Return the number of expected key parameters.  */
+static void
+get_npkey_nskey (int pubkey_algo, size_t *npkey, size_t *nskey)
+{
+  switch (pubkey_algo)
+    {
+    case GCRY_PK_RSA:   *npkey = 2; *nskey = 6; break;
+    case GCRY_PK_ELG:   *npkey = 3; *nskey = 4; break;
+    case GCRY_PK_ELG_E: *npkey = 3; *nskey = 4; break;
+    case GCRY_PK_DSA:   *npkey = 4; *nskey = 5; break;
+    case GCRY_PK_ECC:   *npkey = 1; *nskey = 2; break;
+    default:            *npkey = 0; *nskey = 0; break;
+    }
+}
+
+
 /* Helper for do_unprotect.  PUBKEY_ALOGO is the gcrypt algo number.
    On success R_NPKEY and R_NSKEY receive the number or parameters for
    the algorithm PUBKEY_ALGO and R_SKEYLEN the used length of
@@ -264,7 +283,6 @@ prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize,
                    unsigned int *r_npkey, unsigned int *r_nskey,
                    unsigned int *r_skeylen)
 {
-  gpg_error_t err;
   size_t npkey, nskey, skeylen;
   int i;
 
@@ -293,12 +311,8 @@ prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize,
   /* Get properties of the public key algorithm and do some
      consistency checks.  Note that we need at least NPKEY+1 elements
      in the SKEY array. */
-  if ( (err = gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NPKEY,
-                                 NULL, &npkey))
-       || (err = gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NSKEY,
-                                    NULL, &nskey)))
-    return err;
-  if (!npkey || npkey >= nskey)
+  get_npkey_nskey (pubkey_algo, &npkey, &nskey);
+  if (!npkey || !nskey || npkey >= nskey)
     return gpg_error (GPG_ERR_INTERNAL);
   if (skeylen <= npkey)
     return gpg_error (GPG_ERR_MISSING_VALUE);
@@ -309,7 +323,7 @@ prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize,
      encrypted.  */
   for (i=0; i < npkey; i++)
     {
-      if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
+      if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
         return gpg_error (GPG_ERR_BAD_SECKEY);
     }
 
@@ -329,7 +343,7 @@ prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize,
 static int
 do_unprotect (const char *passphrase,
               int pkt_version, int pubkey_algo, int is_protected,
-              gcry_mpi_t *skey, size_t skeysize,
+              const char *curve, gcry_mpi_t *skey, size_t skeysize,
               int protect_algo, void *protect_iv, size_t protect_ivlen,
               int s2k_mode, int s2k_algo, byte *s2k_salt, u32 s2k_count,
               u16 desired_csum, gcry_sexp_t *r_key)
@@ -353,23 +367,26 @@ do_unprotect (const char *passphrase,
      merely verify the checksum.  */
   if (!is_protected)
     {
-      unsigned char *buffer;
-
       actual_csum = 0;
       for (i=npkey; i < nskey; i++)
         {
-          if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
+          if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
             return gpg_error (GPG_ERR_BAD_SECKEY);
 
-          err = gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, skey[i]);
-          if (!err)
+          if (gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
+            {
+              unsigned int nbits;
+              const unsigned char *buffer;
+              buffer = gcry_mpi_get_opaque (skey[i], &nbits);
+              nbytes = (nbits+7)/8;
+              actual_csum += checksum (buffer, nbytes);
+            }
+          else
             {
-              buffer = (gcry_is_secure (skey[i])?
-                        xtrymalloc_secure (nbytes) : xtrymalloc (nbytes));
-              if (!buffer)
-                return gpg_error_from_syserror ();
-              err = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes,
-                                    NULL, skey[i]);
+              unsigned char *buffer;
+
+              err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, &buffer, &nbytes,
+                                     skey[i]);
               if (!err)
                 actual_csum += checksum (buffer, nbytes);
               xfree (buffer);
@@ -428,7 +445,8 @@ do_unprotect (const char *passphrase,
     {
       int ndata;
       unsigned int ndatabits;
-      unsigned char *p, *data;
+      const unsigned char *p;
+      unsigned char *data;
       u16 csum_pgp7 = 0;
 
       if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE ))
@@ -527,7 +545,7 @@ do_unprotect (const char *passphrase,
 
       for (i = npkey; i < nskey; i++)
         {
-          unsigned char *p;
+          const unsigned char *p;
           size_t ndata;
           unsigned int ndatabits;
 
@@ -580,7 +598,7 @@ do_unprotect (const char *passphrase,
   if (nskey != skeylen)
     err = gpg_error (GPG_ERR_BAD_SECKEY);
   else
-    err = convert_secret_key (r_key, pubkey_algo, skey);
+    err = convert_secret_key (r_key, pubkey_algo, skey, curve);
   if (err)
     return err;
 
@@ -608,6 +626,7 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi)
   err = do_unprotect (pi->pin,
                       arg->is_v4? 4:3,
                       arg->pubkey_algo, arg->is_protected,
+                      arg->curve,
                       arg->skey, arg->skeysize,
                       arg->protect_algo, arg->iv, arg->ivlen,
                       arg->s2k_mode, arg->s2k_algo,
@@ -651,6 +670,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp,
   u32  s2k_count = 0;
   size_t npkey, nskey;
   gcry_mpi_t skey[10];  /* We support up to 9 parameters.  */
+  char *curve = NULL;
   u16 desired_csum;
   int skeyidx = 0;
   gcry_sexp_t s_skey = NULL;
@@ -695,8 +715,6 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp,
       if (!string)
         goto bad_seckey;
       protect_algo = gcry_cipher_map_name (string);
-      if (!protect_algo && !!strcmp (string, "IDEA"))
-        protect_algo = GCRY_CIPHER_IDEA;
       xfree (string);
 
       value = gcry_sexp_nth_data (list, 3, &valuelen);
@@ -739,11 +757,21 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp,
   pubkey_algo = gcry_pk_map_name (string);
   xfree (string);
 
-  if (gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey)
-      || gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
-      || !npkey || npkey >= nskey)
+  get_npkey_nskey (pubkey_algo, &npkey, &nskey);
+  if (!npkey || !nskey || npkey >= nskey)
     goto bad_seckey;
 
+  if (npkey == 1) /* This is ECC */
+    {
+      gcry_sexp_release (list);
+      list = gcry_sexp_find_token (top_list, "curve", 0);
+      if (!list)
+        goto bad_seckey;
+      curve = gcry_sexp_nth_string (list, 1);
+      if (!curve)
+        goto bad_seckey;
+    }
+
   gcry_sexp_release (list);
   list = gcry_sexp_find_token (top_list, "skey", 0);
   if (!list)
@@ -770,15 +798,15 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp,
       value = gcry_sexp_nth_data (list, ++idx, &valuelen);
       if (!value || !valuelen)
         goto bad_seckey;
-      if (is_enc)
+      if (is_enc || curve)
         {
-          void *p = xtrymalloc (valuelen);
-          if (!p)
-            goto outofmem;
-          memcpy (p, value, valuelen);
-          skey[skeyidx] = gcry_mpi_set_opaque (NULL, p, valuelen*8);
+          /* Encrypted parameters and ECC parameters need or can be
+             stored as opaque.  */
+          skey[skeyidx] = gcry_mpi_set_opaque_copy (NULL, value, valuelen*8);
           if (!skey[skeyidx])
             goto outofmem;
+          if (is_enc)
+            gcry_mpi_set_flag (skey[skeyidx], GCRYMPI_FLAG_USER1);
         }
       else
         {
@@ -807,33 +835,24 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp,
   gcry_sexp_release (list); list = NULL;
   gcry_sexp_release (top_list); top_list = NULL;
 
-  /* log_debug ("XXX is_v4=%d\n", is_v4); */
-  /* log_debug ("XXX pubkey_algo=%d\n", pubkey_algo); */
-  /* log_debug ("XXX is_protected=%d\n", is_protected); */
-  /* log_debug ("XXX protect_algo=%d\n", protect_algo); */
-  /* log_printhex ("XXX iv", iv, ivlen); */
-  /* log_debug ("XXX ivlen=%d\n", ivlen); */
-  /* log_debug ("XXX s2k_mode=%d\n", s2k_mode); */
-  /* log_debug ("XXX s2k_algo=%d\n", s2k_algo); */
-  /* log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt); */
-  /* log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count); */
-  /* for (idx=0; skey[idx]; idx++) */
-  /*   { */
-  /*     int is_enc = gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE); */
-  /*     log_info ("XXX skey[%d]%s:", idx, is_enc? " (enc)":""); */
-  /*     if (is_enc) */
-  /*       { */
-  /*         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"); */
-  /*   } */
-
-  err = get_keygrip (pubkey_algo, skey, grip);
+#if 0
+  log_debug ("XXX is_v4=%d\n", is_v4);
+  log_debug ("XXX pubkey_algo=%d\n", pubkey_algo);
+  log_debug ("XXX is_protected=%d\n", is_protected);
+  log_debug ("XXX protect_algo=%d\n", protect_algo);
+  log_printhex ("XXX iv", iv, ivlen);
+  log_debug ("XXX ivlen=%d\n", ivlen);
+  log_debug ("XXX s2k_mode=%d\n", s2k_mode);
+  log_debug ("XXX s2k_algo=%d\n", s2k_algo);
+  log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt);
+  log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count);
+  log_debug ("XXX curve='%s'\n", curve);
+  for (idx=0; skey[idx]; idx++)
+    gcry_log_debugmpi (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_USER1)
+                       ? "skey(e)" : "skey(_)", skey[idx]);
+#endif /*0*/
+
+  err = get_keygrip (pubkey_algo, curve, skey, grip);
   if (err)
     goto leave;
 
@@ -850,7 +869,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp,
       if (err)
         goto leave;
 
-      err = convert_transfer_key (&s_skey, pubkey_algo, skey, s_pgp);
+      err = convert_transfer_key (&s_skey, pubkey_algo, skey, curve, s_pgp);
       if (err)
         goto leave;
     }
@@ -871,6 +890,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp,
       pi_arg.is_v4 = is_v4;
       pi_arg.is_protected = is_protected;
       pi_arg.pubkey_algo = pubkey_algo;
+      pi_arg.curve = curve;
       pi_arg.protect_algo = protect_algo;
       pi_arg.iv = iv;
       pi_arg.ivlen = ivlen;
@@ -929,6 +949,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp,
   err = make_canon_sexp_pad (s_skey, 1, r_key, NULL);
 
  leave:
+  xfree (curve);
   gcry_sexp_release (s_skey);
   gcry_sexp_release (list);
   gcry_sexp_release (top_list);
@@ -1223,11 +1244,9 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
     {
       char countbuf[35];
       membuf_t mbuf;
-      void *format_args_buf_ptr[1];
-      int   format_args_buf_int[1];
       void *format_args[10+2];
-      unsigned int n;
-      gcry_sexp_t tmpkey, tmpsexp = NULL;
+      gcry_sexp_t tmpkey;
+      gcry_sexp_t tmpsexp = NULL;
 
       snprintf (countbuf, sizeof countbuf, "%lu", s2k_count);
 
@@ -1238,11 +1257,8 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
           put_membuf_str (&mbuf, " _ %m");
           format_args[j++] = array + i;
         }
-      put_membuf_str (&mbuf, " e %b");
-      format_args_buf_ptr[0] = gcry_mpi_get_opaque (array[npkey], &n);
-      format_args_buf_int[0] = (n+7)/8;
-      format_args[j++] = format_args_buf_int;
-      format_args[j++] = format_args_buf_ptr;
+      put_membuf_str (&mbuf, " e %m");
+      format_args[j++] = array + npkey;
       put_membuf_str (&mbuf, ")\n");
       put_membuf (&mbuf, "", 1);
 
diff --git a/agent/keyformat.txt b/agent/keyformat.txt
index 3f95dae..42c4b1f 100644
--- a/agent/keyformat.txt
+++ b/agent/keyformat.txt
@@ -211,6 +211,7 @@ This format is used to transfer keys between gpg and gpg-agent.
 (openpgp-private-key
   (version V)
   (algo PUBKEYALGO)
+  (curve CURVENAME)
   (skey _ P1 _ P2 _ P3 ... e PN)
   (csum n)
   (protection PROTTYPE PROTALGO IV S2KMODE S2KHASH S2KSALT S2KCOUNT))
@@ -218,6 +219,7 @@ This format is used to transfer keys between gpg and gpg-agent.
 
 * V is the packet version number (3 or 4).
 * PUBKEYALGO is a Libgcrypt algo name
+* CURVENAME is the name of the curve - only used with ECC.
 * P1 .. PN are the parameters; the public parameters are never encrypted
   the secrect key parameters are encrypted if the "protection" list is
   given.  To make this more explicit each parameter is preceded by a
diff --git a/common/openpgp-oid.c b/common/openpgp-oid.c
index 94a2296..bcb9885 100644
--- a/common/openpgp-oid.c
+++ b/common/openpgp-oid.c
@@ -280,17 +280,20 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits)
       oidstr = "1.3.6.1.4.1.11591.15.1";
       nbits = 255;
     }
-  else if (!strcmp (name, "nistp256"))
+  else if (!strcmp (name, "nistp256") || !strcmp (name, "NIST P-256"))
     {
+      /* Libgcrypt uses "NIST P-256" as standard name for this curve
+         and thus the key generation returns this value.  Thus we
+         allow both strings.  */
       oidstr = "1.2.840.10045.3.1.7";
       nbits = 256;
     }
-  else if (!strcmp (name, "nistp384"))
+  else if (!strcmp (name, "nistp384") || !strcmp (name, "NIST P-384"))
     {
       oidstr = "1.3.132.0.34";
       nbits = 384;
     }
-  else if (!strcmp (name, "nistp521"))
+  else if (!strcmp (name, "nistp521") || !strcmp (name, "NIST P-521"))
     {
       oidstr = "1.3.132.0.35";
       nbits = 521;
diff --git a/g10/import.c b/g10/import.c
index 8223041..2b219a2 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1128,37 +1128,6 @@ import_one (ctrl_t ctrl,
 }
 
 
-/* Extract one MPI value from the S-expression PKEY which is expected
-   to hold a "public-key".  Returns NULL on error.  */
-static gcry_mpi_t
-one_mpi_from_pkey (gcry_sexp_t pkey, const char *name, size_t namelen)
-{
-  gcry_sexp_t list, l2;
-  gcry_mpi_t a;
-
-  list = gcry_sexp_find_token (pkey, "public-key", 0);
-  if (!list)
-    return NULL;
-  l2 = gcry_sexp_cadr (list);
-  gcry_sexp_release (list);
-  list = l2;
-  if (!list)
-    return NULL;
-
-  l2 = gcry_sexp_find_token (list, name, namelen);
-  if (!l2)
-    {
-      gcry_sexp_release (list);
-      return NULL;
-    }
-  a = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
-  gcry_sexp_release (l2);
-  gcry_sexp_release (list);
-
-  return a;
-}
-
-
 /* Transfer all the secret keys in SEC_KEYBLOCK to the gpg-agent.  The
    function prints diagnostics and returns an error code. */
 static gpg_error_t
@@ -1174,18 +1143,15 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
   int nskey;
   membuf_t mbuf;
   int i, j;
-  unsigned int n;
-  void *format_args_buf_ptr[PUBKEY_MAX_NSKEY];
-  int   format_args_buf_int[PUBKEY_MAX_NSKEY];
   void *format_args[2*PUBKEY_MAX_NSKEY];
   gcry_sexp_t skey, prot, tmpsexp;
+  gcry_sexp_t curve = NULL;
   unsigned char *transferkey = NULL;
   size_t transferkeylen;
   gcry_cipher_hd_t cipherhd = NULL;
   unsigned char *wrappedkey = NULL;
   size_t wrappedkeylen;
   char *cache_nonce = NULL;
-  gcry_mpi_t ecc_params[5] = {NULL, NULL, NULL, NULL, NULL};
 
   /* Get the current KEK.  */
   err = agent_keywrap_key (ctrl, 0, &kek, &keklen);
@@ -1263,65 +1229,30 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
           || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
           || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
         {
-          /* We need special treatment for ECC algorithms.  OpenPGP
-             stores only the curve name but the agent expects a full
-             key.  This is so that we can keep all curve name
-             validation code out of gpg-agent.  */
-#if PUBKEY_MAX_NSKEY < 7
-#error  PUBKEY_MAX_NSKEY too low for ECC
-#endif
-          char *curve = openpgp_oid_to_str (pk->pkey[0]);
-          if (!curve)
+          /* The ECC case.  */
+          char *curvestr = openpgp_oid_to_str (pk->pkey[0]);
+          if (!curvestr)
             err = gpg_error_from_syserror ();
           else
             {
-              gcry_sexp_t cparam = gcry_pk_get_param (GCRY_PK_ECC, curve);
-
-              xfree (curve);
-              if (!cparam)
-                err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
-              else
+              err = gcry_sexp_build (&curve, NULL, "(curve %s)", curvestr);
+              xfree (curvestr);
+              if (!err)
                 {
-                  const char *s;
-
-                  /* Append the curve parameters P, A, B, G and N.  */
-                  for (i=j=0; !err && *(s = "pabgn"+i); i++)
-                    {
-                      ecc_params[i] = one_mpi_from_pkey (cparam, s, 1);
-                      if (!ecc_params[i])
-                        err = gpg_error (GPG_ERR_INV_CURVE);
-                      else
-                        {
-                          put_membuf_str (&mbuf, " _ %m");
-                          format_args[j++] = ecc_params+i;
-                        }
-                    }
-                  gcry_sexp_release (cparam);
-                  if (!err)
-                    {
-                      /* Append the public key element Q.  */
-                      put_membuf_str (&mbuf, " _ %m");
-                      format_args[j++] = pk->pkey + 1;
-
-                      /* Append the secret key element D.  Note that
-                         for ECDH we need to skip PKEY[2] because this
-                         holds the KEK which is not needed.  */
-                      i = pk->pubkey_algo == PUBKEY_ALGO_ECDH? 3 : 2;
-                      if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
-                        {
-                          put_membuf_str (&mbuf, " e %b");
-                          format_args_buf_ptr[i]
-                            = gcry_mpi_get_opaque (pk->pkey[i],&n);
-                          format_args_buf_int[i] = (n+7)/8;
-                          format_args[j++] = format_args_buf_int + i;
-                          format_args[j++] = format_args_buf_ptr + i;
-                        }
-                      else
-                        {
-                          put_membuf_str (&mbuf, " _ %m");
-                          format_args[j++] = pk->pkey + i;
-                        }
-                    }
+                  j = 0;
+                  /* Append the public key element Q.  */
+                  put_membuf_str (&mbuf, " _ %m");
+                  format_args[j++] = pk->pkey + 1;
+
+                  /* Append the secret key element D.  For ECDH we
+                     skip PKEY[2] because this holds the KEK which is
+                     not needed by gpg-agent.  */
+                  i = pk->pubkey_algo == PUBKEY_ALGO_ECDH? 3 : 2;
+                  if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_USER1))
+                    put_membuf_str (&mbuf, " e %m");
+                  else
+                    put_membuf_str (&mbuf, " _ %m");
+                  format_args[j++] = pk->pkey + i;
                 }
             }
         }
@@ -1331,23 +1262,16 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
           for (i=j=0; i < nskey; i++)
             {
               if (!pk->pkey[i])
-                ; /* Protected keys only have NPKEY+1 elements.  */
-              else if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
-                {
-                  put_membuf_str (&mbuf, " e %b");
-                  format_args_buf_ptr[i] = gcry_mpi_get_opaque (pk->pkey[i],&n);
-                  format_args_buf_int[i] = (n+7)/8;
-                  format_args[j++] = format_args_buf_int + i;
-                  format_args[j++] = format_args_buf_ptr + i;
-                }
+                continue; /* Protected keys only have NPKEY+1 elements.  */
+
+              if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_USER1))
+                put_membuf_str (&mbuf, " e %m");
               else
-                {
-                  put_membuf_str (&mbuf, " _ %m");
-                  format_args[j++] = pk->pkey + i;
-                }
+                put_membuf_str (&mbuf, " _ %m");
+              format_args[j++] = pk->pkey + i;
             }
         }
-      put_membuf_str (&mbuf, ")\n");
+      put_membuf_str (&mbuf, ")");
       put_membuf (&mbuf, "", 1);
       if (err)
         xfree (get_membuf (&mbuf, NULL));
@@ -1398,12 +1322,13 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
                                "(openpgp-private-key\n"
                                " (version %d)\n"
                                " (algo %s)\n"
-                               " %S\n"
+                               " %S%S\n"
                                " (csum %d)\n"
                                " %S)\n",
                                pk->version,
                                openpgp_pk_algo_name (pk->pubkey_algo),
-                               skey, (int)(unsigned long)ski->csum, prot);
+                               curve, skey,
+                               (int)(unsigned long)ski->csum, prot);
       gcry_sexp_release (skey);
       gcry_sexp_release (prot);
       if (!err)
@@ -1463,8 +1388,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
     }
 
  leave:
-  for (i=0; i < DIM (ecc_params); i++)
-    gcry_mpi_release (ecc_params[i]);
+  gcry_sexp_release (curve);
   xfree (cache_nonce);
   xfree (wrappedkey);
   xfree (transferkey);
diff --git a/g10/keygen.c b/g10/keygen.c
index f3052e4..314cf9b 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -2086,29 +2086,30 @@ ask_keysize (int algo, unsigned int primary_keysize)
 }
 
 
-/* Ask for the key size.  ALGO is the algorithm.  If PRIMARY_KEYSIZE
-   is not 0, the function asks for the size of the encryption
-   subkey. */
+/* Ask for the curve.  ALGO is the selected algorithm which this
+   function may adjust.  Returns a malloced string with the name of
+   the curve.  */
 static char *
-ask_curve (void)
+ask_curve (int *algo)
 {
   struct {
     const char *name;
     int available;
     int expert_only;
+    int fix_curve;
     const char *pretty_name;
   } curves[] = {
 #if GPG_USE_EDDSA
-    { "Ed25519",         0, 0, "Curve 25519" },
+    { "Curve25519",      0, 0, 1, "Curve 25519" },
 #endif
 #if GPG_USE_ECDSA || GPG_USE_ECDH
-    { "NIST P-256",      0, 1, },
-    { "NIST P-384",      0, 0, },
-    { "NIST P-521",      0, 1, },
-    { "brainpoolP256r1", 0, 1, "Brainpool P-256" },
-    { "brainpoolP384r1", 0, 1, "Brainpool P-384" },
-    { "brainpoolP512r1", 0, 1, "Brainpool P-512" },
-    { "secp256k1", 0, 1 },
+    { "NIST P-256",      0, 1, 0, },
+    { "NIST P-384",      0, 0, 0, },
+    { "NIST P-521",      0, 1, 0, },
+    { "brainpoolP256r1", 0, 1, 0, "Brainpool P-256" },
+    { "brainpoolP384r1", 0, 1, 0, "Brainpool P-384" },
+    { "brainpoolP512r1", 0, 1, 0, "Brainpool P-512" },
+    { "secp256k1",       0, 1, 0  },
 #endif
   };
   int idx;
@@ -2127,9 +2128,14 @@ ask_curve (void)
       if (!opt.expert && curves[idx].expert_only)
         continue;
 
+      /* FIXME: The strcmp below is a temporary hack during
+         development.  It shall be removed as soon as we have proper
+         Curve25519 support in Libgcrypt.  */
       gcry_sexp_release (keyparms);
       rc = gcry_sexp_build (&keyparms, NULL,
-                            "(public-key(ecc(curve %s)))", curves[idx].name);
+                            "(public-key(ecc(curve %s)))",
+                            (!strcmp (curves[idx].name, "Curve25519")
+                             ? "Ed25519" : curves[idx].name));
       if (rc)
         continue;
       if (!gcry_pk_get_curve (keyparms, 0, NULL))
@@ -2171,7 +2177,22 @@ ask_curve (void)
         tty_printf (_("Invalid selection.\n"));
       else
         {
-          result = xstrdup (curves[idx].name);
+          if (curves[idx].fix_curve)
+            log_info ("WARNING: Curve25519 is an experimental algorithm and"
+                      " not yet specified by OpenPGP.  The current"
+                      " implementation may change with the next GnuPG release"
+                      " and thus rendering the key unusable!\n");
+
+          /* If the user selected a signing algorithm and Curve25519
+             we need to update the algo and and the curve name.  */
+          if ((*algo == PUBKEY_ALGO_ECDSA || *algo == PUBKEY_ALGO_EDDSA)
+              && curves[idx].fix_curve)
+            {
+              *algo = PUBKEY_ALGO_EDDSA;
+              result = xstrdup ("Ed25519");
+            }
+          else
+            result = xstrdup (curves[idx].name);
           break;
         }
     }
@@ -3459,16 +3480,16 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno,
         {
           /* Create primary and subkey at once.  */
           both = 1;
-          r = xmalloc_clear( sizeof *r + 20 );
-          r->key = pKEYTYPE;
-          sprintf( r->u.value, "%d", algo );
-          r->next = para;
-          para = r;
           if (algo == PUBKEY_ALGO_ECDSA
               || algo == PUBKEY_ALGO_EDDSA
               || algo == PUBKEY_ALGO_ECDH)
             {
-              curve = ask_curve ();
+              curve = ask_curve (&algo);
+              r = xmalloc_clear( sizeof *r + 20 );
+              r->key = pKEYTYPE;
+              sprintf( r->u.value, "%d", algo);
+              r->next = para;
+              para = r;
               nbits = 0;
               r = xmalloc_clear (sizeof *r + strlen (curve));
               r->key = pKEYCURVE;
@@ -3478,6 +3499,11 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno,
             }
           else
             {
+              r = xmalloc_clear( sizeof *r + 20 );
+              r->key = pKEYTYPE;
+              sprintf( r->u.value, "%d", algo);
+              r->next = para;
+              para = r;
               nbits = ask_keysize (algo, 0);
               r = xmalloc_clear( sizeof *r + 20 );
               r->key = pKEYLENGTH;
@@ -3501,9 +3527,43 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno,
           strcpy( r->u.value, "encrypt" );
           r->next = para;
           para = r;
+
+          if (algo == PUBKEY_ALGO_ECDSA
+              || algo == PUBKEY_ALGO_EDDSA
+              || algo == PUBKEY_ALGO_ECDH)
+            {
+              if (algo == PUBKEY_ALGO_EDDSA
+                  && subkey_algo == PUBKEY_ALGO_ECDH)
+                {
+                  /* Need to switch to a different curve for the
+                     encryption key.  */
+                  xfree (curve);
+                  curve = xstrdup ("Curve25519");
+                }
+              r = xmalloc_clear (sizeof *r + strlen (curve));
+              r->key = pSUBKEYCURVE;
+              strcpy (r->u.value, curve);
+              r->next = para;
+              para = r;
+            }
         }
-      else
+      else /* Create only a single key.  */
         {
+          /* For ECC we need to ask for the curve before storing the
+             algo becuase ask_curve may change the algo.  */
+          if (algo == PUBKEY_ALGO_ECDSA
+              || algo == PUBKEY_ALGO_EDDSA
+              || algo == PUBKEY_ALGO_ECDH)
+            {
+              curve = ask_curve (&algo);
+              nbits = 0;
+              r = xmalloc_clear (sizeof *r + strlen (curve));
+              r->key = pKEYCURVE;
+              strcpy (r->u.value, curve);
+              r->next = para;
+              para = r;
+            }
+
           r = xmalloc_clear( sizeof *r + 20 );
           r->key = pKEYTYPE;
           sprintf( r->u.value, "%d", algo );
@@ -3528,13 +3588,7 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno,
           || algo == PUBKEY_ALGO_EDDSA
           || algo == PUBKEY_ALGO_ECDH)
         {
-          if (!both)
-            curve = ask_curve ();
-          r = xmalloc_clear (sizeof *r + strlen (curve));
-          r->key = both? pSUBKEYCURVE : pKEYCURVE;
-          strcpy (r->u.value, curve);
-          r->next = para;
-          para = r;
+          /* The curve has already been set.  */
         }
       else
         {
@@ -4031,11 +4085,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
   else if (algo == PUBKEY_ALGO_ECDSA
            || algo == PUBKEY_ALGO_EDDSA
            || algo == PUBKEY_ALGO_ECDH)
-    {
-      curve = ask_curve ();
-      if (curve && !strcmp (curve, "Ed25519"))
-        algo = PUBKEY_ALGO_EDDSA;
-    }
+    curve = ask_curve (&algo);
   else
     nbits = ask_keysize (algo, 0);
 
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index f708788..424b052 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -2240,6 +2240,11 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
 	  pk->pkey[npkey] = gcry_mpi_set_opaque (NULL,
 						 read_rest (inp, pktlen),
 						 pktlen * 8);
+          /* Mark that MPI as protected - we need this information for
+             importing a key.  The OPAQUE flag can't be used because
+             we also store public EdDSA values in opaque MPIs.  */
+          if (pk->pkey[npkey])
+            gcry_mpi_set_flag (pk->pkey[npkey], GCRYMPI_FLAG_USER1);
 	  pktlen = 0;
 	  if (list_mode)
             es_fprintf (listfp, "\tskey[%d]: [v4 protected]\n", npkey);
@@ -2252,6 +2257,8 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
 	      if (ski->is_protected)
 		{
 		  pk->pkey[i] = read_protected_v3_mpi (inp, &pktlen);
+                  if (pk->pkey[i])
+                    gcry_mpi_set_flag (pk->pkey[i], GCRYMPI_FLAG_USER1);
 		  if (list_mode)
 		    es_fprintf (listfp, "\tskey[%d]: [v3 protected]\n", i);
 		}
diff --git a/tests/openpgp/ecc.test b/tests/openpgp/ecc.test
index 062a1ae..cb04467 100755
--- a/tests/openpgp/ecc.test
+++ b/tests/openpgp/ecc.test
@@ -188,7 +188,7 @@ echo 'This is one line' >z
 for msg in $tests; do
    info "checking: $msg"
    eval "(IFS=; echo \"\$$msg\")" >x
-   $GPG -o y --yes x || error "decryption of $msg failed"
+   PINENTRY_USER_DATA=ecc $GPG -o y --yes x || error "decryption of $msg failed"
    cmp y z || error "$msg: mismatch"
 done
 
@@ -204,7 +204,7 @@ for i in $plain_files $data_files ; do
   for k in $mainkeyids ; do
     info "file: $i key: $k"
     $GPG ${opt_always} -e -o x --yes -r $k $i
-    $GPG -o y --yes x
+    PINENTRY_USER_DATA=ecc $GPG -o y --yes x
     cmp $i y || error "$i,$k: mismatch"
   done
 done
@@ -217,7 +217,7 @@ info "Checking ECC signing and verifiction."
 for i in $plain_files $data_files ; do
   for k in $mainkeyids ; do
     info "file: $i key: $k"
-    $GPG -s -o x --yes -u $k $i
+    PINENTRY_USER_DATA=ecc $GPG -s -o x --yes -u $k $i
     $GPG -o y --yes x || error "verify of $i,$k failed"
     cmp $i y || error "$i,$k: mismatch"
   done

commit bdb9c2b314400da9155b8a924e22e486793dda89
Author: Werner Koch <wk at gnupg.org>
Date:   Wed May 7 12:39:43 2014 +0200

    kbx: Add experimental support for EDDSA.
    
    * kbx/keybox-openpgp.c (parse_key): Use algo constants and add
    experimental support for EdDSA.

diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c
index 82bc934..6ae6c44 100644
--- a/kbx/keybox-openpgp.c
+++ b/kbx/keybox-openpgp.c
@@ -199,23 +199,24 @@ parse_key (const unsigned char *data, size_t datalen,
 
   switch (algorithm)
     {
-    case 1:
-    case 2:
-    case 3: /* RSA */
+    case PUBKEY_ALGO_RSA:
+    case PUBKEY_ALGO_RSA_E:
+    case PUBKEY_ALGO_RSA_S:
       npkey = 2;
       break;
-    case 16:
-    case 20: /* Elgamal */
+    case PUBKEY_ALGO_ELGAMAL_E:
+    case PUBKEY_ALGO_ELGAMAL:
       npkey = 3;
       break;
-    case 17: /* DSA */
+    case PUBKEY_ALGO_DSA:
       npkey = 4;
       break;
-    case 18: /* ECDH */
+    case PUBKEY_ALGO_ECDH:
       npkey = 3;
       is_ecc = 1;
       break;
-    case 19: /* ECDSA */
+    case PUBKEY_ALGO_ECDSA:
+    case PUBKEY_ALGO_EDDSA:
       npkey = 2;
       is_ecc = 1;
       break;

commit a63ed9875830e5b3b4d48b7d97d24c18de36b326
Author: Werner Koch <wk at gnupg.org>
Date:   Wed May 7 08:51:11 2014 +0200

    agent: Remove greeting message.
    
    * agent/gpg-agent.c (main): Remove greeting.  Make --no-greeting a
    dummy.

diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 5319e49..9ec13ee 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -612,8 +612,6 @@ main (int argc, char **argv )
   unsigned configlineno;
   int parse_debug = 0;
   int default_config =1;
-  int greeting = 0;
-  int nogreeting = 0;
   int pipe_server = 0;
   int is_daemon = 0;
   int nodetach = 0;
@@ -811,7 +809,7 @@ main (int argc, char **argv )
 		goto next_pass;
 	    }
           break;
-        case oNoGreeting: nogreeting = 1; break;
+        case oNoGreeting: /* Dummy option.  */ break;
         case oNoVerbose: opt.verbose = 0; break;
         case oNoOptions: break; /* no-options */
         case oHomedir: opt.homedir = pargs.r.ret_str; break;
@@ -882,25 +880,10 @@ main (int argc, char **argv )
   configname = NULL;
   if (log_get_errorcount(0))
     exit(2);
-  if (nogreeting )
-    greeting = 0;
 
   /* Turn the homedir into an absolute one. */
   opt.homedir = make_absfilename (opt.homedir, NULL);
 
-
-  if (greeting)
-    {
-      es_fprintf (es_stderr, "%s %s; %s\n",
-                  strusage(11), strusage(13), strusage(14) );
-      es_fprintf (es_stderr, "%s\n", strusage(15) );
-    }
-#ifdef IS_DEVELOPMENT_VERSION
-  /* We don't want to print it here because gpg-agent is useful of its
-     own and quite matured.  */
-  /*log_info ("NOTE: this is a development version!\n");*/
-#endif
-
   /* Print a warning if an argument looks like an option.  */
   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
     {

commit 6477e51919ef97f0f9cc05d10cdc7aa2b89faafe
Author: Werner Koch <wk at gnupg.org>
Date:   Tue May 6 09:49:26 2014 +0200

    Use "samethread" mode keyword for some es_fopenmem.
    
    * dirmngr/ks-engine-hkp.c (armor_data): Add mode keyword.
    * g10/call-dirmngr.c (ks_put_inq_cb): Ditto.
    * scd/atr.c (atr_dump): Ditto.

diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index c115cf5..8c3384d 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -925,7 +925,7 @@ armor_data (char **r_string, const void *data, size_t datalen)
 
   *r_string = NULL;
 
-  fp = es_fopenmem (0, "rw");
+  fp = es_fopenmem (0, "rw,samethread");
   if (!fp)
     return gpg_error_from_syserror ();
 
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index 73f829e..5bddbbe 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -593,7 +593,7 @@ ks_put_inq_cb (void *opaque, const char *line)
       estream_t fp;
 
       /* Parse the keyblock and send info lines back to the server.  */
-      fp = es_fopenmem (0, "rw");
+      fp = es_fopenmem (0, "rw,samethread");
       if (!fp)
         err = gpg_error_from_syserror ();
 
diff --git a/scd/atr.c b/scd/atr.c
index b8668a4..c3fa49f 100644
--- a/scd/atr.c
+++ b/scd/atr.c
@@ -50,7 +50,7 @@ atr_dump (const void *buffer, size_t buflen)
   unsigned char chksum;
   char *result;
 
-  fp = es_fopenmem (0, "rwb");
+  fp = es_fopenmem (0, "rwb,samethread");
   if (!fp)
     return NULL;
 

-----------------------------------------------------------------------

Summary of changes:
 agent/cvt-openpgp.c     |  184 +++++++------
 agent/gpg-agent.c       |   19 +-
 agent/keyformat.txt     |    2 +
 common/openpgp-oid.c    |    9 +-
 dirmngr/ks-engine-hkp.c |    2 +-
 g10/call-dirmngr.c      |    2 +-
 g10/import.c            |  140 +++-------
 g10/keygen.c            |  116 +++++---
 g10/keylist.c           |   16 +-
 g10/mainproc.c          |  686 ++++++++++++++++++++++++-----------------------
 g10/misc.c              |    4 +-
 g10/parse-packet.c      |    7 +
 kbx/keybox-openpgp.c    |   17 +-
 scd/atr.c               |    2 +-
 tests/openpgp/ecc.test  |    6 +-
 15 files changed, 605 insertions(+), 607 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list