Expand a ~ in the ca-cert-file argument.
[gnupg.git] / sm / fingerprint.c
index 7fe619c..4704f59 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -42,8 +41,9 @@
    If there is a problem , the function does never return NULL but a
    digest of all 0xff.
  */
-char *
-gpgsm_get_fingerprint (ksba_cert_t cert, int algo, char *array, int *r_len)
+unsigned char *
+gpgsm_get_fingerprint (ksba_cert_t cert, int algo,
+                       unsigned char *array, int *r_len)
 {
   gcry_md_hd_t md;
   int rc, len;
@@ -59,6 +59,19 @@ gpgsm_get_fingerprint (ksba_cert_t cert, int algo, char *array, int *r_len)
   if (r_len)
     *r_len = len;
 
+  /* Fist check whether we have cached the fingerprint.  */
+  if (algo == GCRY_MD_SHA1)
+    {
+      size_t buflen;
+
+      assert (len >= 20);
+      if (!ksba_cert_get_user_data (cert, "sha1-fingerprint", 
+                                    array, len, &buflen)
+          && buflen == 20)
+        return array;
+    }
+
+  /* No, need to compute it.  */
   rc = gcry_md_open (&md, algo, 0);
   if (rc)
     {
@@ -77,6 +90,12 @@ gpgsm_get_fingerprint (ksba_cert_t cert, int algo, char *array, int *r_len)
     }
   gcry_md_final (md);
   memcpy (array, gcry_md_read(md, algo), len );
+  gcry_md_close (md);
+
+  /* Cache an SHA-1 fingerprint.  */
+  if ( algo == GCRY_MD_SHA1 )
+    ksba_cert_set_user_data (cert, "sha1-fingerprint", array, 20);
+
   return array;
 }
 
@@ -87,7 +106,7 @@ gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo)
 {
   unsigned char digest[MAX_DIGEST_LEN];
   char *buf;
-  int len, i;
+  int len;
 
   if (!algo)
     algo = GCRY_MD_SHA1;
@@ -96,9 +115,7 @@ gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo)
   assert (len <= MAX_DIGEST_LEN );
   gpgsm_get_fingerprint (cert, algo, digest, NULL);
   buf = xmalloc (len*3+1);
-  *buf = 0;
-  for (i=0; i < len; i++ )
-    sprintf (buf+strlen(buf), i? ":%02X":"%02X", digest[i]);
+  bin2hexcolon (digest, len, buf);
   return buf;
 }
 
@@ -109,7 +126,7 @@ gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo)
 {
   unsigned char digest[MAX_DIGEST_LEN];
   char *buf;
-  int len, i;
+  int len;
 
   if (!algo)
     algo = GCRY_MD_SHA1;
@@ -117,31 +134,32 @@ gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo)
   len = gcry_md_get_algo_dlen (algo);
   assert (len <= MAX_DIGEST_LEN );
   gpgsm_get_fingerprint (cert, algo, digest, NULL);
-  buf = xmalloc (len*3+1);
-  *buf = 0;
-  for (i=0; i < len; i++ )
-    sprintf (buf+strlen(buf), "%02X", digest[i]);
+  buf = xmalloc (len*2+1);
+  bin2hex (digest, len, buf);
   return buf;
 }
 
 /* Return a certificate ID.  These are the last 4 bytes of the SHA-1
-   fingerprint. */
+   fingerprint.  If R_HIGH is not NULL the next 4 bytes are stored
+   there. */
 unsigned long
-gpgsm_get_short_fingerprint (ksba_cert_t cert)
+gpgsm_get_short_fingerprint (ksba_cert_t cert, unsigned long *r_high)
 {
   unsigned char digest[20];
 
   gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL);
+  if (r_high)
+    *r_high = ((digest[12]<<24)|(digest[13]<<16)|(digest[14]<< 8)|digest[15]);
   return ((digest[16]<<24)|(digest[17]<<16)|(digest[18]<< 8)|digest[19]);
 }
 
 \f
 /* Return the so called KEYGRIP which is the SHA-1 hash of the public
-   key parameters expressed as an canoncial encoded S-Exp.  array must
-   be 20 bytes long. returns the array or a newly allocated one if the
-   passed one was NULL */
-char *
-gpgsm_get_keygrip (ksba_cert_t cert, char *array)
+   key parameters expressed as an canoncial encoded S-Exp.  ARRAY must
+   be 20 bytes long.  Returns ARRAY or a newly allocated buffer if ARRAY was
+   given as NULL.  May return NULL on error.  */
+unsigned char *
+gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array)
 {
   gcry_sexp_t s_pkey;
   int rc;
@@ -160,7 +178,7 @@ gpgsm_get_keygrip (ksba_cert_t cert, char *array)
       log_error ("libksba did not return a proper S-Exp\n");
       return NULL;
     }
-  rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
+  rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n);
   xfree (p);
   if (rc)
     {
@@ -181,19 +199,19 @@ gpgsm_get_keygrip (ksba_cert_t cert, char *array)
   return array;
 }
 
-/* Return an allocated buffer with the keygrip of CERT in from of an
-   hexstring.  NULL is returned in case of error */
+/* Return an allocated buffer with the keygrip of CERT encoded as a
+   hexstring.  NULL is returned in case of error */
 char *
 gpgsm_get_keygrip_hexstring (ksba_cert_t cert)
 {
   unsigned char grip[20];
-  char *buf, *p;
-  int i;
+  char *buf;
 
-  gpgsm_get_keygrip (cert, grip);
-  buf = p = xmalloc (20*2+1);
-  for (i=0; i < 20; i++, p += 2 )
-    sprintf (p, "%02X", grip[i]);
+  if (!gpgsm_get_keygrip (cert, grip))
+    return NULL;
+  buf = xtrymalloc (20*2+1);
+  if (buf)
+    bin2hex (grip, 20, buf);
   return buf;
 }
 
@@ -223,7 +241,7 @@ gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits)
       xfree (p);
       return 0;
     }
-  rc = gcry_sexp_sscan (&s_pkey, NULL, p, n);
+  rc = gcry_sexp_sscan (&s_pkey, NULL, (char *)p, n);
   xfree (p);
   if (rc)
     return 0;
@@ -272,7 +290,7 @@ char *
 gpgsm_get_certid (ksba_cert_t cert)
 {
   ksba_sexp_t serial;
-  unsigned char *p;
+  char *p;
   char *endp;
   unsigned char hash[20];
   unsigned long n;
@@ -288,7 +306,7 @@ gpgsm_get_certid (ksba_cert_t cert)
   serial = ksba_cert_get_serial (cert);
   if (!serial)
     return NULL; /* oops: no serial number */
-  p = serial;
+  p = (char *)serial;
   if (*p != '(')
     {
       log_error ("Ooops: invalid serial number\n");
@@ -317,7 +335,7 @@ gpgsm_get_certid (ksba_cert_t cert)
     sprintf (endp, "%02X", hash[i]);
   *endp++ = '.';
   for (i=0; i < n; i++, endp += 2)
-    sprintf (endp, "%02X", p[i]);
+    sprintf (endp, "%02X", ((unsigned char*)p)[i]);
   *endp = 0;
 
   xfree (serial);
@@ -327,5 +345,3 @@ gpgsm_get_certid (ksba_cert_t cert)
 
 
 
-
-