gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
[gnupg.git] / g10 / keyid.c
index 1284287..5fa44ef 100644 (file)
 
 #define KEYID_STR_SIZE 19
 
+#ifdef HAVE_UNSIGNED_TIME_T
+# define IS_INVALID_TIME_T(a) ((a) == (time_t)(-1))
+#else
+  /* Error or 32 bit time_t and value after 2038-01-19.  */
+# define IS_INVALID_TIME_T(a) ((a) < 0)
+#endif
+
 
 /* Return a letter describing the public key algorithms.  */
 int
@@ -47,9 +54,12 @@ pubkey_letter( int algo )
     case PUBKEY_ALGO_RSA:      return 'R' ;
     case PUBKEY_ALGO_RSA_E:    return 'r' ;
     case PUBKEY_ALGO_RSA_S:    return 's' ;
-    case PUBKEY_ALGO_ELGAMAL_E: return 'g';
+    case PUBKEY_ALGO_ELGAMAL_E: return 'g' ;
     case PUBKEY_ALGO_ELGAMAL:   return 'G' ;
     case PUBKEY_ALGO_DSA:      return 'D' ;
+    case PUBKEY_ALGO_EDDSA:    return 'E' ;    /* ECC EdDSA (sign only) */
+    case PUBKEY_ALGO_ECDSA:    return 'E' ;    /* ECC DSA (sign only)   */
+    case PUBKEY_ALGO_ECDH:     return 'e' ;    /* ECC DH (encrypt only) */
     default: return '?';
     }
 }
@@ -72,6 +82,11 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
   if(pk->version<4)
     n+=2;
 
+  /* FIXME: We can avoid the extra malloc by calling only the first
+     mpi_print here which computes the required length and calling the
+     real mpi_print only at the end.  The speed advantage would only be
+     for ECC (opaque MPIs) or if we could implement an mpi_print
+     variant with a callback handler to do the hashing.  */
   if (npkey==0 && pk->pkey[0]
       && gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE))
     {
@@ -81,16 +96,30 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
     }
   else
     {
-      for(i=0; i < npkey; i++ )
+      for (i=0; i < npkey; i++ )
         {
-          if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i]))
-            BUG ();
-          pp[i] = xmalloc (nbytes);
-          if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes,
-                              &nbytes, pk->pkey[i]))
-            BUG ();
-          nn[i] = nbytes;
-          n += nn[i];
+          if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
+            {
+              const void *p;
+
+              p = gcry_mpi_get_opaque (pk->pkey[i], &nbits);
+              pp[i] = xmalloc ((nbits+7)/8);
+              memcpy (pp[i], p, (nbits+7)/8);
+              nn[i] = (nbits+7)/8;
+              n += nn[i];
+            }
+          else
+            {
+              if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0,
+                                  &nbytes, pk->pkey[i]))
+                BUG ();
+              pp[i] = xmalloc (nbytes);
+              if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes,
+                                  &nbytes, pk->pkey[i]))
+                BUG ();
+              nn[i] = nbytes;
+              n += nn[i];
+            }
         }
     }
 
@@ -110,7 +139,7 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
       u16 days=0;
       if(pk->expiredate)
        days=(u16)((pk->expiredate - pk->timestamp) / 86400L);
+
       gcry_md_putc ( md, days >> 8 );
       gcry_md_putc ( md, days );
     }
@@ -161,7 +190,7 @@ v3_keyid (gcry_mpi_t a, u32 *ki)
     BUG ();
   if (nbytes < 8) /* oops */
     ki[0] = ki[1] = 0;
-  else 
+  else
     {
       p = buffer + nbytes - 8;
       ki[0] = (p[0] << 24) | (p[1] <<16) | (p[2] << 8) | p[3];
@@ -198,7 +227,7 @@ keystrlen(void)
 
 const char *
 keystr (u32 *keyid)
-{  
+{
   static char keyid_str[KEYID_STR_SIZE];
 
   switch (opt.keyid_format)
@@ -209,7 +238,7 @@ keystr (u32 *keyid)
 
     case KF_LONG:
       if (keyid[0])
-       snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX", 
+       snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX",
                   (ulong)keyid[0], (ulong)keyid[1]);
       else
        snprintf (keyid_str, sizeof keyid_str, "%08lX", (ulong)keyid[1]);
@@ -221,12 +250,12 @@ keystr (u32 *keyid)
 
     case KF_0xLONG:
       if(keyid[0])
-       snprintf (keyid_str, sizeof keyid_str, "0x%08lX%08lX", 
+       snprintf (keyid_str, sizeof keyid_str, "0x%08lX%08lX",
                   (ulong)keyid[0],(ulong)keyid[1]);
       else
        snprintf (keyid_str, sizeof keyid_str, "0x%08lX", (ulong)keyid[1]);
       break;
-      
+
     default:
       BUG();
     }
@@ -237,7 +266,7 @@ keystr (u32 *keyid)
 
 const char *
 keystr_with_sub (u32 *main_kid, u32 *sub_kid)
-{  
+{
   static char buffer[KEYID_STR_SIZE+1+KEYID_STR_SIZE];
   char *p;
 
@@ -391,7 +420,7 @@ keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
       else
         keyid_from_pk (&pk, keyid);
     }
-  else 
+  else
     {
       const byte *dp = fprint;
       keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
@@ -405,7 +434,7 @@ keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
 u32
 keyid_from_sig (PKT_signature *sig, u32 *keyid)
 {
-  if( keyid ) 
+  if( keyid )
     {
       keyid[0] = sig->keyid[0];
       keyid[1] = sig->keyid[1];
@@ -420,13 +449,13 @@ namehash_from_uid (PKT_user_id *uid)
   if (!uid->namehash)
     {
       uid->namehash = xmalloc (20);
-      
+
       if (uid->attrib_data)
        rmd160_hash_buffer (uid->namehash, uid->attrib_data, uid->attrib_len);
       else
        rmd160_hash_buffer (uid->namehash, uid->name, uid->len);
     }
-  
+
   return uid->namehash;
 }
 
@@ -446,13 +475,9 @@ mk_datestr (char *buffer, time_t atime)
 {
   struct tm *tp;
 
-  /* Note: VMS uses an unsigned time_t thus the compiler yields a
-     warning here.  You may ignore this warning or def out this test
-     for VMS.  The proper way to handle this would be a configure test
-     to a detect properly implemented unsigned time_t.  */
-  if ( atime < 0 ) /* 32 bit time_t and after 2038-01-19 */
-    strcpy (buffer, "????" "-??" "-??"); /* mark this as invalid */
-  else 
+  if (IS_INVALID_TIME_T (atime))
+    strcpy (buffer, "????" "-??" "-??"); /* Mark this as invalid. */
+  else
     {
       tp = gmtime (&atime);
       sprintf (buffer,"%04d-%02d-%02d",
@@ -472,7 +497,7 @@ datestr_from_pk (PKT_public_key *pk)
 {
   static char buffer[11+5];
   time_t atime = pk->timestamp;
-  
+
   return mk_datestr (buffer, atime);
 }
 
@@ -505,7 +530,7 @@ expirestr_from_sig (PKT_signature *sig)
 {
   static char buffer[11+5];
   time_t atime;
-  
+
   if (!sig->expiredate)
     return _("never     ");
   atime=sig->expiredate;
@@ -578,7 +603,7 @@ const char *
 colon_datestr_from_sig (PKT_signature *sig)
 {
   static char buf[20];
-  
+
   snprintf (buf, sizeof buf, "%lu", (ulong)sig->timestamp);
   return buf;
 }
@@ -608,21 +633,21 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
   const byte *dp;
   size_t len, nbytes;
   int i;
-  
+
   if ( pk->version < 4 )
     {
       if ( is_RSA(pk->pubkey_algo) )
         {
           /* RSA in version 3 packets is special. */
           gcry_md_hd_t md;
-          
+
           if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0))
             BUG ();
-          if ( pubkey_get_npkey (pk->pubkey_algo) > 1 ) 
+          if ( pubkey_get_npkey (pk->pubkey_algo) > 1 )
             {
               for (i=0; i < 2; i++)
                 {
-                  if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, 
+                  if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0,
                                       &nbytes, pk->pkey[i]))
                     BUG ();
                   /* fixme: Better allocate BUF on the stack */
@@ -649,10 +674,10 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
           memset (array,0,16);
         }
     }
-  else 
+  else
     {
       gcry_md_hd_t md;
-      
+
       md = do_fingerprint_md(pk);
       dp = gcry_md_read( md, 0 );
       len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
@@ -664,7 +689,7 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
       pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
       gcry_md_close( md);
     }
-  
+
   *ret_len = len;
   return array;
 }
@@ -681,7 +706,7 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
 {
   gpg_error_t err;
   gcry_sexp_t s_pkey;
-  
+
   if (DBG_PACKET)
     log_debug ("get_keygrip for public key\n");
 
@@ -709,11 +734,28 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
                              pk->pkey[0], pk->pkey[1]);
       break;
 
+    case PUBKEY_ALGO_EDDSA:
+    case PUBKEY_ALGO_ECDSA:
+    case PUBKEY_ALGO_ECDH:
+      {
+        char *curve = openpgp_oid_to_str (pk->pkey[0]);
+        if (!curve)
+          err = gpg_error_from_syserror ();
+        else
+          {
+            err = gcry_sexp_build (&s_pkey, NULL,
+                                   "(public-key(ecc(curve%s)(q%m)))",
+                                   curve, pk->pkey[1]);
+            xfree (curve);
+          }
+      }
+      break;
+
     default:
       err = gpg_error (GPG_ERR_PUBKEY_ALGO);
       break;
     }
-  
+
   if (err)
     return err;
 
@@ -729,7 +771,7 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
       /* FIXME: Save the keygrip in PK.  */
     }
   gcry_sexp_release (s_pkey);
-  
+
   return 0;
 }
 
@@ -757,4 +799,3 @@ hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip)
     }
   return err;
 }
-