[ksba][PATCH 1/2] Merge _ksba_keyinfo_to_sexp into cryptval_to_sexp

Dmitry Eremin-Solenikov dbaryshkov at gmail.com
Mon Jan 20 01:33:34 CET 2014


* src/keyinfo.c (cryptval_to_sexp): Add mode 2 support suitable to
  replace parse keyinfo data.
* src/keyinfo.c (_ksba_keyinfo_to_sexp): Use new cryptval_to_sexp
  mode dedicated to keyinfo parsing.

--
_ksba_keyinfo_to_sexp and cryptval_to_sexp share lots of common code.
Merge them to be less error prone.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 src/keyinfo.c | 356 +++++++++++++++++++++++-----------------------------------
 1 file changed, 138 insertions(+), 218 deletions(-)

diff --git a/src/keyinfo.c b/src/keyinfo.c
index 02dc7ae..0f4f95f 100644
--- a/src/keyinfo.c
+++ b/src/keyinfo.c
@@ -640,213 +640,6 @@ get_stringbuf (struct stringbuf *sb)
   return p;
 }
 
-
-/* Assume that der is a buffer of length DERLEN with a DER encoded
- Asn.1 structure like this:
-
-  keyInfo ::= SEQUENCE {
-                 SEQUENCE {
-                    algorithm    OBJECT IDENTIFIER,
-                    parameters   ANY DEFINED BY algorithm OPTIONAL }
-                 publicKey  BIT STRING }
-
-  The function parses this structure and create a SEXP suitable to be
-  used as a public key in Libgcrypt.  The S-Exp will be returned in a
-  string which the caller must free.
-
-  We don't pass an ASN.1 node here but a plain memory block.  */
-
-gpg_error_t
-_ksba_keyinfo_to_sexp (const unsigned char *der, size_t derlen,
-                       ksba_sexp_t *r_string)
-{
-  gpg_error_t err;
-  int c;
-  size_t nread, off, len, parm_off, parm_len;
-  int parm_type;
-  char *parm_oid = NULL;
-  int algoidx;
-  int is_bitstr;
-  const unsigned char *parmder = NULL;
-  size_t parmderlen = 0;
-  const unsigned char *ctrl;
-  const char *elem;
-  struct stringbuf sb;
-
-  *r_string = NULL;
-
-  /* check the outer sequence */
-  if (!derlen)
-    return gpg_error (GPG_ERR_INV_KEYINFO);
-  c = *der++; derlen--;
-  if ( c != 0x30 )
-    return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */
-  TLV_LENGTH(der);
-  /* and now the inner part */
-  err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr,
-                       &parm_off, &parm_len, &parm_type);
-  if (err)
-    return err;
-
-  /* look into our table of supported algorithms */
-  for (algoidx=0; pk_algo_table[algoidx].oid; algoidx++)
-    {
-      if ( len == pk_algo_table[algoidx].oidlen
-           && !memcmp (der+off, pk_algo_table[algoidx].oid, len))
-        break;
-    }
-  if (!pk_algo_table[algoidx].oid)
-    return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
-  if (!pk_algo_table[algoidx].supported)
-    return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
-
-  if (parm_off && parm_len && parm_type == TYPE_OBJECT_ID)
-    parm_oid = ksba_oid_to_str (der+parm_off, parm_len);
-  else if (parm_off && parm_len)
-    {
-      parmder = der + parm_off;
-      parmderlen = parm_len;
-    }
-
-  der += nread;
-  derlen -= nread;
-
-  if (is_bitstr)
-    { /* Funny: X.509 defines the signature value as a bit string but
-         CMS as an octet string - for ease of implementation we always
-         allow both */
-      if (!derlen)
-        {
-          xfree (parm_oid);
-          return gpg_error (GPG_ERR_INV_KEYINFO);
-        }
-      c = *der++; derlen--;
-      if (c)
-        fprintf (stderr, "warning: number of unused bits is not zero\n");
-    }
-
-  /* fixme: we should calculate the initial length form the size of the
-     sequence, so that we don't need a realloc later */
-  init_stringbuf (&sb, 100);
-  put_stringbuf (&sb, "(10:public-key(");
-
-  /* fixme: we can also use the oidstring here and prefix it with
-     "oid." - this way we can pass more information into Libgcrypt or
-     whatever library is used */
-  put_stringbuf_sexp (&sb, pk_algo_table[algoidx].algo_string);
-
-  /* Insert the curve name for ECC. */
-  if (pk_algo_table[algoidx].pkalgo == PKALGO_ECC && parm_oid)
-    {
-      put_stringbuf (&sb, "(");
-      put_stringbuf_sexp (&sb, "curve");
-      put_stringbuf_sexp (&sb, parm_oid);
-      put_stringbuf (&sb, ")");
-    }
-
-  /* If parameters are given and we have a description for them, parse
-     them. */
-  if (parmder && parmderlen
-      && pk_algo_table[algoidx].parmelem_string
-      && pk_algo_table[algoidx].parmctrl_string)
-    {
-      elem = pk_algo_table[algoidx].parmelem_string;
-      ctrl = pk_algo_table[algoidx].parmctrl_string;
-      for (; *elem; ctrl++, elem++)
-        {
-          int is_int;
-
-          if ( (*ctrl & 0x80) && !elem[1] )
-            {
-              /* Hack to allow reading a raw value.  */
-              is_int = 1;
-              len = parmderlen;
-            }
-          else
-            {
-              if (!parmderlen)
-                {
-                  xfree (parm_oid);
-                  return gpg_error (GPG_ERR_INV_KEYINFO);
-                }
-              c = *parmder++; parmderlen--;
-              if ( c != *ctrl )
-                {
-                  xfree (parm_oid);
-                  return gpg_error (GPG_ERR_UNEXPECTED_TAG);
-                }
-              is_int = c == 0x02;
-              TLV_LENGTH (parmder);
-            }
-          if (is_int && *elem != '-')  /* Take this integer.  */
-            {
-              char tmp[2];
-
-              put_stringbuf (&sb, "(");
-              tmp[0] = *elem; tmp[1] = 0;
-              put_stringbuf_sexp (&sb, tmp);
-              put_stringbuf_mem_sexp (&sb, parmder, len);
-              parmder += len;
-              parmderlen -= len;
-              put_stringbuf (&sb, ")");
-            }
-        }
-    }
-
-
-  /* FIXME: We don't release the stringbuf in case of error
-     better let the macro jump to a label */
-  elem = pk_algo_table[algoidx].elem_string;
-  ctrl = pk_algo_table[algoidx].ctrl_string;
-  for (; *elem; ctrl++, elem++)
-    {
-      int is_int;
-
-      if ( (*ctrl & 0x80) && !elem[1] )
-        {
-          /* Hack to allow reading a raw value.  */
-          is_int = 1;
-          len = derlen;
-        }
-      else
-        {
-          if (!derlen)
-            {
-              xfree (parm_oid);
-              return gpg_error (GPG_ERR_INV_KEYINFO);
-            }
-          c = *der++; derlen--;
-          if ( c != *ctrl )
-            {
-              xfree (parm_oid);
-              return gpg_error (GPG_ERR_UNEXPECTED_TAG);
-            }
-          is_int = c == 0x02;
-          TLV_LENGTH (der);
-        }
-      if (is_int && *elem != '-')  /* Take this integer.  */
-        {
-          char tmp[2];
-
-          put_stringbuf (&sb, "(");
-          tmp[0] = *elem; tmp[1] = 0;
-          put_stringbuf_sexp (&sb, tmp);
-          put_stringbuf_mem_sexp (&sb, der, len);
-          der += len;
-          derlen -= len;
-          put_stringbuf (&sb, ")");
-        }
-    }
-  put_stringbuf (&sb, "))");
-  xfree (parm_oid);
-
-  *r_string = get_stringbuf (&sb);
-  if (!*r_string)
-    return gpg_error (GPG_ERR_ENOMEM);
-
-  return 0;
-}
-
 
 /* Match the algorithm string given in BUF which is of length BUFLEN
    with the known algorithms from our table and returns the table
@@ -1572,17 +1365,24 @@ _ksba_algoinfo_from_sexp (ksba_const_sexp_t sexp,
 
 
 /* Mode 0: work as described under _ksba_sigval_to_sexp
-   mode 1: work as described under _ksba_encval_to_sexp */
+   Mode 1: work as described under _ksba_encval_to_sexp
+   Mode 1: work as described under _ksba_keyinfo_to_sexp
+   */
 static gpg_error_t
 cryptval_to_sexp (int mode, const unsigned char *der, size_t derlen,
                   ksba_sexp_t *r_string)
 {
   gpg_error_t err;
   const struct algo_table_s *algo_table;
+  const char *head;
   int c;
-  size_t nread, off, len;
+  size_t nread, off, len, parm_off, parm_len;
+  int parm_type;
+  char *parm_oid = NULL;
   int algoidx;
   int is_bitstr;
+  const unsigned char *parmder = NULL;
+  size_t parmderlen = 0;
   const unsigned char *ctrl;
   const char *elem;
   struct stringbuf sb;
@@ -1590,14 +1390,34 @@ cryptval_to_sexp (int mode, const unsigned char *der, size_t derlen,
   /* FIXME: The entire function is very similar to keyinfo_to_sexp */
   *r_string = NULL;
 
-  if (!mode)
-    algo_table = sig_algo_table;
-  else
-    algo_table = enc_algo_table;
-
+  switch (mode)
+    {
+    case 0:
+      algo_table = sig_algo_table;
+      head = "(7:sig-val(";
+      break;
+    case 1:
+      algo_table = enc_algo_table;
+      head = "(7:enc-val(";
+      break;
+    case 2:
+      algo_table = pk_algo_table;
+      head = "(10:public-key(";
+
+      /* check the outer sequence */
+      if (!derlen)
+        return gpg_error (GPG_ERR_INV_KEYINFO);
+      c = *der++; derlen--;
+      if ( c != 0x30 )
+        return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */
+      TLV_LENGTH(der);
+      break;
+    default:
+      return gpg_error (GPG_ERR_INV_KEYINFO);
+    }
 
   err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr,
-                       NULL, NULL, NULL);
+                       &parm_off, &parm_len, &parm_type);
   if (err)
     return err;
 
@@ -1613,6 +1433,14 @@ cryptval_to_sexp (int mode, const unsigned char *der, size_t derlen,
   if (!algo_table[algoidx].supported)
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
 
+  if (parm_off && parm_len && parm_type == TYPE_OBJECT_ID)
+    parm_oid = ksba_oid_to_str (der+parm_off, parm_len);
+  else if (parm_off && parm_len)
+    {
+      parmder = der + parm_off;
+      parmderlen = parm_len;
+    }
+
   der += nread;
   derlen -= nread;
 
@@ -1630,9 +1458,71 @@ cryptval_to_sexp (int mode, const unsigned char *der, size_t derlen,
   /* fixme: we should calculate the initial length form the size of the
      sequence, so that we don't neen a realloc later */
   init_stringbuf (&sb, 100);
-  put_stringbuf (&sb, mode? "(7:enc-val(":"(7:sig-val(");
+  put_stringbuf (&sb, head);
+
+  /* fixme: in mode 2 we can also use the oidstring here and prefix it
+     with "oid." - this way we can pass more information into Libgcrypt or
+     whatever library is used */
   put_stringbuf_sexp (&sb, algo_table[algoidx].algo_string);
 
+  /* Insert the curve name for ECC. */
+  if (pk_algo_table[algoidx].pkalgo == PKALGO_ECC && parm_oid)
+    {
+      put_stringbuf (&sb, "(");
+      put_stringbuf_sexp (&sb, "curve");
+      put_stringbuf_sexp (&sb, parm_oid);
+      put_stringbuf (&sb, ")");
+    }
+
+  /* If parameters are given and we have a description for them, parse
+     them. */
+  if (parmder && parmderlen
+      && pk_algo_table[algoidx].parmelem_string
+      && pk_algo_table[algoidx].parmctrl_string)
+    {
+      elem = pk_algo_table[algoidx].parmelem_string;
+      ctrl = pk_algo_table[algoidx].parmctrl_string;
+      for (; *elem; ctrl++, elem++)
+        {
+          int is_int;
+
+          if ( (*ctrl & 0x80) && !elem[1] )
+            {
+              /* Hack to allow reading a raw value.  */
+              is_int = 1;
+              len = parmderlen;
+            }
+          else
+            {
+              if (!parmderlen)
+                {
+                  xfree (parm_oid);
+                  return gpg_error (GPG_ERR_INV_KEYINFO);
+                }
+              c = *parmder++; parmderlen--;
+              if ( c != *ctrl )
+                {
+                  xfree (parm_oid);
+                  return gpg_error (GPG_ERR_UNEXPECTED_TAG);
+                }
+              is_int = c == 0x02;
+              TLV_LENGTH (parmder);
+            }
+          if (is_int && *elem != '-')  /* Take this integer.  */
+            {
+              char tmp[2];
+
+              put_stringbuf (&sb, "(");
+              tmp[0] = *elem; tmp[1] = 0;
+              put_stringbuf_sexp (&sb, tmp);
+              put_stringbuf_mem_sexp (&sb, parmder, len);
+              parmder += len;
+              parmderlen -= len;
+              put_stringbuf (&sb, ")");
+            }
+        }
+    }
+
   /* FIXME: We don't release the stringbuf in case of error
      better let the macro jump to a label */
   elem = algo_table[algoidx].elem_string;
@@ -1649,10 +1539,16 @@ cryptval_to_sexp (int mode, const unsigned char *der, size_t derlen,
       else
         {
           if (!derlen)
-            return gpg_error (GPG_ERR_INV_KEYINFO);
+            {
+              xfree (parm_oid);
+              return gpg_error (GPG_ERR_INV_KEYINFO);
+            }
           c = *der++; derlen--;
           if ( c != *ctrl )
-            return gpg_error (GPG_ERR_UNEXPECTED_TAG);
+            {
+              xfree (parm_oid);
+              return gpg_error (GPG_ERR_UNEXPECTED_TAG);
+            }
           is_int = c == 0x02;
           TLV_LENGTH (der);
         }
@@ -1670,6 +1566,7 @@ cryptval_to_sexp (int mode, const unsigned char *der, size_t derlen,
         }
     }
   put_stringbuf (&sb, ")");
+  xfree (parm_oid);
   if (!mode && algo_table[algoidx].digest_string)
     {
       /* Insert the hash algorithm if included in the OID.  */
@@ -1744,3 +1641,26 @@ _ksba_encval_to_sexp (const unsigned char *der, size_t derlen,
 {
   return cryptval_to_sexp (1, der, derlen, r_string);
 }
+
+
+/* Assume that der is a buffer of length DERLEN with a DER encoded
+ Asn.1 structure like this:
+
+  keyInfo ::= SEQUENCE {
+                 SEQUENCE {
+                    algorithm    OBJECT IDENTIFIER,
+                    parameters   ANY DEFINED BY algorithm OPTIONAL }
+                 publicKey  BIT STRING }
+
+  The function parses this structure and create a SEXP suitable to be
+  used as a public key in Libgcrypt.  The S-Exp will be returned in a
+  string which the caller must free.
+
+  We don't pass an ASN.1 node here but a plain memory block.  */
+
+gpg_error_t
+_ksba_keyinfo_to_sexp (const unsigned char *der, size_t derlen,
+                       ksba_sexp_t *r_string)
+{
+  return cryptval_to_sexp (2, der, derlen, r_string);
+}
-- 
1.8.5.2




More information about the Gnupg-devel mailing list