scd:piv: Allow writecert to only write matching certs.
[gnupg.git] / scd / app-help.c
index 45c7586..f0f551c 100644 (file)
@@ -1,5 +1,5 @@
 /* app-help.c - Application helper functions
- *     Copyright (C) 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -14,7 +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, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include "scdaemon.h"
 #include "app-common.h"
 #include "iso7816.h"
-#include "tlv.h"
+#include "../common/tlv.h"
+
+
+/* Count the number of bits, assuming that A represents an unsigned
+ * big integer of length LEN bytes.  If A is NULL a length of 0 is
+ * returned. */
+unsigned int
+app_help_count_bits (const unsigned char *a, size_t len)
+{
+  unsigned int n = len * 8;
+  int i;
+
+  if (!a)
+    return 0;
+
+  for (; len && !*a; len--, a++, n -=8)
+    ;
+  if (len)
+    {
+      for (i=7; i && !(*a & (1<<i)); i--)
+        n--;
+    }
+  return n;
+}
+
 
 /* Return the KEYGRIP for the certificate CERT as an hex encoded
    string in the user provided buffer HEXKEYGRIP which must be of at
@@ -39,7 +63,6 @@ app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip)
   ksba_sexp_t p;
   size_t n;
   unsigned char array[20];
-  int i;
 
   p = ksba_cert_get_public_key (cert);
   if (!p)
@@ -58,13 +81,51 @@ app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip)
     }
   gcry_sexp_release (s_pkey);
 
-  for (i=0; i < 20; i++)
-    sprintf (hexkeygrip+i*2, "%02X", array[i]);
+  bin2hex (array, 20, hexkeygrip);
 
   return 0;
 }
 
 
+gpg_error_t
+app_help_pubkey_from_cert (const void *cert, size_t certlen,
+                           unsigned char **r_pk, size_t *r_pklen)
+{
+  gpg_error_t err;
+  ksba_cert_t kc;
+  unsigned char *pk;
+  size_t pklen;
+
+  *r_pk = NULL;
+  *r_pklen = 0;
+
+  err = ksba_cert_new (&kc);
+  if (err)
+    return err;
+
+  err = ksba_cert_init_from_mem (kc, cert, certlen);
+  if (err)
+    goto leave;
+
+  pk = ksba_cert_get_public_key (kc);
+  if (!pk)
+    {
+      err = gpg_error (GPG_ERR_NO_PUBKEY);
+      goto leave;
+    }
+  pklen = gcry_sexp_canon_len (pk, 0, NULL, &err);
+
+ leave:
+  if (!err)
+    {
+      *r_pk = pk;
+      *r_pklen = pklen;
+    }
+  else
+    ksba_free (pk);
+  ksba_cert_release (kc);
+  return err;
+}
 
 /* Given the SLOT and the File ID FID, return the length of the
    certificate contained in that file. Returns 0 if the file does not
@@ -84,7 +145,7 @@ app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff)
   int class, tag, constructed, ndef;
   size_t resultlen, objlen, hdrlen;
 
-  err = iso7816_select_file (slot, fid, 0, NULL, NULL);
+  err = iso7816_select_file (slot, fid, 0);
   if (err)
     {
       log_info ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
@@ -98,7 +159,7 @@ app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff)
                  fid, gpg_strerror (err));
       return 0;
     }
-  
+
   if (!buflen || *buffer == 0xff)
     {
       log_info ("no certificate contained in FID 0x%04X\n", fid);
@@ -123,8 +184,7 @@ app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff)
   if ( !(class == CLASS_UNIVERSAL &&  constructed
          && (tag == TAG_SEQUENCE || tag == TAG_SET)))
     {
-      log_info ("contents of FID 0x%04X does not look like a certificate\n",
-                fid);
+      log_info ("data at FID 0x%04X does not look like a certificate\n", fid);
       return 0;
     }
 
@@ -157,5 +217,3 @@ app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff)
 
   return resultlen;
 }
-
-