[ksba][PATCH 2/2] Merge functions that convert from sexp to der

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


* src/keyinfo.c (cryptval_from_sexp): New. Contains code merged from
  _ksba_keyinfo_from_sexp and _ksba_algoinfo_from_sexp functions.
* src/keyinfo.c (_ksba_algoinfo_from_sexp, _ksba_keyinfo_from_sexp): Use
  cryptval_from_sexp function.

Merge two functions translating S-expressions to DER representation.
They share great amount of code, so merge is benefitable.

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

diff --git a/src/keyinfo.c b/src/keyinfo.c
index 0f4f95f..cdea1e6 100644
--- a/src/keyinfo.c
+++ b/src/keyinfo.c
@@ -702,12 +702,11 @@ oid_from_buffer (const unsigned char *buf, int buflen, int *oidlen,
   return pk_algo_table[i].oid;
 }
 
-
-/* Take a public-key S-Exp and convert it into a DER encoded
-   publicKeyInfo */
-gpg_error_t
-_ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
-                         unsigned char **r_der, size_t *r_derlen)
+/* Mode 0: work with public key
+   Mode 1: work with signature */
+static gpg_error_t
+cryptval_from_sexp (int mode, ksba_const_sexp_t sexp,
+                     unsigned char **r_der, size_t *r_derlen)
 {
   gpg_error_t err;
   const unsigned char *s;
@@ -748,9 +747,13 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
   if (!n || *s != ':')
     return gpg_error (GPG_ERR_INV_SEXP); /* we don't allow empty lengths */
   s++;
-  if (n != 10 || memcmp (s, "public-key", 10))
+  if (n == 7 && !memcmp (s, "sig-val", 7))
+    s += 7;
+  else if (n == 10 && !memcmp (s, "public-key", 10))
+    s += 10;
+  else
     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
-  s += 10;
+
   if (*s != '(')
     return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP);
   s++;
@@ -761,7 +764,7 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
   if (!n || *s != ':')
     return gpg_error (GPG_ERR_INV_SEXP); /* we don't allow empty lengths */
   s++;
-  oid = oid_from_buffer (s, n, &oidlen, &pkalgo, 0);
+  oid = oid_from_buffer (s, n, &oidlen, &pkalgo, mode);
   if (!oid)
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
   s += n;
@@ -809,9 +812,9 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
   algoparmdesc = NULL;
   switch (pkalgo)
     {
-    case PKALGO_RSA: parmdesc = "ne"; break;
-    case PKALGO_DSA: parmdesc = "y" ; algoparmdesc = "pqg"; break;
-    case PKALGO_ECC: parmdesc = "Cq"; break;
+    case PKALGO_RSA: parmdesc = mode ? "" : "ne"; break;
+    case PKALGO_DSA: parmdesc = mode ? "" : "y" ; algoparmdesc = "pqg"; break;
+    case PKALGO_ECC: parmdesc = mode ? "C" : "Cq"; break;
     default: return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
     }
 
@@ -868,71 +871,74 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
      2. We create the outer sequence include the algorithm identifier
         and the bit string from step 1.
    */
-  if (pkalgo == PKALGO_ECC)
+  if (!mode)
     {
-      /* Write the bit string header and the number of unused bits. */
-      err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL,
-                                0, parm[idxtbl[1]].valuelen + 1);
-      if (!err)
-        err = ksba_writer_write (writer, "", 1);
-      /* And the actual raw value.  */
-      if (!err)
-        err = ksba_writer_write (writer, parm[idxtbl[1]].value,
-                                 parm[idxtbl[1]].valuelen);
-      if (err)
-        goto leave;
-
-    }
-  else /* RSA and DSA */
-    {
-      /* Calculate the size of the sequence value and the size of the
-         bit string value.  NOt ethat in case there is only one
-         integer to write, no sequence is used.  */
-      for (n=0, i=0; i < idxtbllen; i++ )
+      if (pkalgo == PKALGO_ECC)
         {
-          n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
-                                   parm[idxtbl[i]].valuelen);
-          n += parm[idxtbl[i]].valuelen;
-        }
+          /* Write the bit string header and the number of unused bits. */
+          err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL,
+                                    0, parm[idxtbl[1]].valuelen + 1);
+          if (!err)
+            err = ksba_writer_write (writer, "", 1);
+          /* And the actual raw value.  */
+          if (!err)
+            err = ksba_writer_write (writer, parm[idxtbl[1]].value,
+                                     parm[idxtbl[1]].valuelen);
+          if (err)
+            goto leave;
 
-      n1 = 1; /* # of unused bits.  */
-      if (idxtbllen > 1)
-        n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
-      n1 += n;
+        }
+      else /* RSA and DSA */
+        {
+          /* Calculate the size of the sequence value and the size of the
+             bit string value.  NOt ethat in case there is only one
+             integer to write, no sequence is used.  */
+          for (n=0, i=0; i < idxtbllen; i++ )
+            {
+              n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
+                                       parm[idxtbl[i]].valuelen);
+              n += parm[idxtbl[i]].valuelen;
+            }
 
-      /* Write the bit string header and the number of unused bits. */
-      err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL,
-                                0, n1);
-      if (!err)
-        err = ksba_writer_write (writer, "", 1);
-      if (err)
-        goto leave;
+          n1 = 1; /* # of unused bits.  */
+          if (idxtbllen > 1)
+            n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
+          n1 += n;
 
-      /* Write the sequence tag and the integers. */
-      if (idxtbllen > 1)
-        err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1,n);
-      if (err)
-        goto leave;
-      for (i=0; i < idxtbllen; i++)
-        {
-          /* fixme: we should make sure that the integer conforms to the
-             ASN.1 encoding rules. */
-          err  = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
-                                     parm[idxtbl[i]].valuelen);
+          /* Write the bit string header and the number of unused bits. */
+          err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL,
+                                    0, n1);
           if (!err)
-            err = ksba_writer_write (writer, parm[idxtbl[i]].value,
-                                     parm[idxtbl[i]].valuelen);
+            err = ksba_writer_write (writer, "", 1);
+          if (err)
+            goto leave;
+
+          /* Write the sequence tag and the integers. */
+          if (idxtbllen > 1)
+            err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1,n);
           if (err)
             goto leave;
+          for (i=0; i < idxtbllen; i++)
+            {
+              /* fixme: we should make sure that the integer conforms to the
+                 ASN.1 encoding rules. */
+              err  = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
+                                         parm[idxtbl[i]].valuelen);
+              if (!err)
+                err = ksba_writer_write (writer, parm[idxtbl[i]].value,
+                                         parm[idxtbl[i]].valuelen);
+              if (err)
+                goto leave;
+            }
         }
-    }
 
-  /* Get the encoded bit string. */
-  bitstr_value = ksba_writer_snatch_mem (writer, &bitstr_len);
-  if (!bitstr_value)
-    {
-      err = gpg_error (GPG_ERR_ENOMEM);
-      goto leave;
+      /* Get the encoded bit string. */
+      bitstr_value = ksba_writer_snatch_mem (writer, &bitstr_len);
+      if (!bitstr_value)
+        {
+          err = gpg_error (GPG_ERR_ENOMEM);
+          goto leave;
+        }
     }
 
   /* If the algorithmIdentifier requires a sequence with parameters,
@@ -1017,14 +1023,17 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
       n += _ksba_ber_count_tl (TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
     }
 
-  n1 = n;
-  n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
-  n1 += bitstr_len;
+  if (!mode)
+    {
+      n1 = n;
+      n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
+      n1 += bitstr_len;
 
-  /* The outer sequence.  */
-  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n1);
-  if (err)
-    goto leave;
+      /* The outer sequence.  */
+      err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n1);
+      if (err)
+        goto leave;
+    }
 
   /* The sequence.  */
   err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
@@ -1058,9 +1067,12 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
     goto leave;
 
   /* Append the pre-constructed bit string.  */
-  err = ksba_writer_write (writer, bitstr_value, bitstr_len);
-  if (err)
-    goto leave;
+  if (!mode)
+    {
+      err = ksba_writer_write (writer, bitstr_value, bitstr_len);
+      if (err)
+        goto leave;
+    }
 
   /* Get the result. */
   *r_der = ksba_writer_snatch_mem (writer, r_derlen);
@@ -1074,6 +1086,15 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
   return err;
 }
 
+/* Take a public-key S-Exp and convert it into a DER encoded
+   publicKeyInfo */
+gpg_error_t
+_ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
+                         unsigned char **r_der, size_t *r_derlen)
+{
+  return cryptval_from_sexp (0, sexp, r_der, r_derlen);
+}
+
 
 /* Take a sig-val s-expression and convert it into a DER encoded
    algorithmInfo.  Unfortunately this function clones a lot of code
@@ -1082,284 +1103,7 @@ gpg_error_t
 _ksba_algoinfo_from_sexp (ksba_const_sexp_t sexp,
                           unsigned char **r_der, size_t *r_derlen)
 {
-  gpg_error_t err;
-  const unsigned char *s;
-  char *endp;
-  unsigned long n;
-  const unsigned char *oid;
-  int oidlen;
-  unsigned char *curve_oid = NULL;
-  size_t curve_oidlen;
-  pkalgo_t pkalgo;
-  int i;
-  struct {
-    const char *name;
-    int namelen;
-    const unsigned char *value;
-    int valuelen;
-  } parm[10];
-  int parmidx;
-  int idxtbl[10];
-  int idxtbllen;
-  const char *parmdesc, *algoparmdesc;
-  ksba_writer_t writer = NULL;
-  void *algoparmseq_value = NULL;
-  size_t algoparmseq_len;
-
-  if (!sexp)
-    return gpg_error (GPG_ERR_INV_VALUE);
-
-  s = sexp;
-  if (*s != '(')
-    return gpg_error (GPG_ERR_INV_SEXP);
-  s++;
-
-  n = strtoul (s, &endp, 10);
-  s = endp;
-  if (!n || *s != ':')
-    return gpg_error (GPG_ERR_INV_SEXP); /* We don't allow empty lengths.  */
-  s++;
-  if (n == 7 && !memcmp (s, "sig-val", 7))
-    s += 7;
-  else if (n == 10 && !memcmp (s, "public-key", 10))
-    s += 10;
-  else
-    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
-
-  if (*s != '(')
-    return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP);
-  s++;
-
-  /* Break out the algorithm ID */
-  n = strtoul (s, &endp, 10);
-  s = endp;
-  if (!n || *s != ':')
-    return gpg_error (GPG_ERR_INV_SEXP); /* We don't allow empty lengths.  */
-  s++;
-  oid = oid_from_buffer (s, n, &oidlen, &pkalgo, 1);
-  if (!oid)
-    return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
-  s += n;
-
-  /* Collect all the values */
-  for (parmidx = 0; *s != ')' ; parmidx++)
-    {
-      if (parmidx >= DIM(parm))
-        return gpg_error (GPG_ERR_GENERAL);
-      if (*s != '(')
-        return gpg_error (digitp(s)? GPG_ERR_UNKNOWN_SEXP:GPG_ERR_INV_SEXP);
-      s++;
-      n = strtoul (s, &endp, 10);
-      s = endp;
-      if (!n || *s != ':')
-        return gpg_error (GPG_ERR_INV_SEXP);
-      s++;
-      parm[parmidx].name = s;
-      parm[parmidx].namelen = n;
-      s += n;
-      if (!digitp(s))
-        return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
-
-      n = strtoul (s, &endp, 10);
-      s = endp;
-      if (!n || *s != ':')
-        return gpg_error (GPG_ERR_INV_SEXP);
-      s++;
-      parm[parmidx].value = s;
-      parm[parmidx].valuelen = n;
-      s += n;
-      if ( *s != ')')
-        return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
-      s++;
-    }
-  s++;
-  /* We need another closing parenthesis. */
-  if ( *s != ')' )
-    return gpg_error (GPG_ERR_INV_SEXP);
-
-  /* Describe the parameters in the order we want them and construct
-     IDXTBL to access them.  For DSA wie also set algoparmdesc so
-     that we can later build the parameters for the
-     algorithmIdentifier.  */
-  algoparmdesc = NULL;
-  switch (pkalgo)
-    {
-    case PKALGO_RSA: parmdesc = ""; break;
-    case PKALGO_DSA: parmdesc = "" ; algoparmdesc = "pqg"; break;
-    case PKALGO_ECC: parmdesc = "C"; break;
-    default: return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
-    }
-
-  idxtbllen = 0;
-  for (s = parmdesc; *s; s++)
-    {
-      for (i=0; i < parmidx; i++)
-        {
-          assert (idxtbllen < DIM (idxtbl));
-          switch (*s)
-            {
-            case 'C': /* Magic value for "curve".  */
-              if (parm[i].namelen == 5 && !memcmp (parm[i].name, "curve", 5))
-                {
-                  idxtbl[idxtbllen++] = i;
-                  i = parmidx; /* Break inner loop.  */
-                }
-              break;
-            default:
-              if (parm[i].namelen == 1 && parm[i].name[0] == *s)
-                {
-                  idxtbl[idxtbllen++] = i;
-                  i = parmidx; /* Break inner loop.  */
-                }
-              break;
-            }
-        }
-    }
-  if (idxtbllen != strlen (parmdesc))
-    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
-
-  if (pkalgo == PKALGO_ECC)
-    {
-      curve_oid = get_ecc_curve_oid (parm[idxtbl[0]].value,
-                                     parm[idxtbl[0]].valuelen,
-                                     &curve_oidlen);
-      if (!curve_oid)
-        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
-    }
-
-
-  /* Create write object. */
-  err = ksba_writer_new (&writer);
-  if (err)
-    goto leave;
-  err = ksba_writer_set_mem (writer, 1024);
-  if (err)
-    goto leave;
-
-  /* Create the sequence of the algorithm identifier.  */
-
-  /* If the algorithmIdentifier requires a sequence with parameters,
-     build them now.  We can reuse the IDXTBL for that.  */
-  if (algoparmdesc)
-    {
-      idxtbllen = 0;
-      for (s = algoparmdesc; *s; s++)
-        {
-          for (i=0; i < parmidx; i++)
-            {
-              assert (idxtbllen < DIM (idxtbl));
-              if (parm[i].namelen == 1 && parm[i].name[0] == *s)
-                {
-                  idxtbl[idxtbllen++] = i;
-                  break;
-                }
-            }
-        }
-      if (idxtbllen != strlen (algoparmdesc))
-        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
-
-      err = ksba_writer_set_mem (writer, 1024);
-      if (err)
-        goto leave;
-
-      /* Calculate the size of the sequence.  */
-      for (n=0, i=0; i < idxtbllen; i++ )
-        {
-          n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
-                                   parm[idxtbl[i]].valuelen);
-          n += parm[idxtbl[i]].valuelen;
-        }
-
-      /* Write the sequence tag followed by the integers. */
-      err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
-      if (err)
-        goto leave;
-      for (i=0; i < idxtbllen; i++)
-        {
-          err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
-                                    parm[idxtbl[i]].valuelen);
-          if (!err)
-            err = ksba_writer_write (writer, parm[idxtbl[i]].value,
-                                     parm[idxtbl[i]].valuelen);
-          if (err)
-            goto leave;
-        }
-
-      /* Get the encoded sequence.  */
-      algoparmseq_value = ksba_writer_snatch_mem (writer, &algoparmseq_len);
-      if (!algoparmseq_value)
-        {
-          err = gpg_error (GPG_ERR_ENOMEM);
-          goto leave;
-        }
-    }
-  else
-    algoparmseq_len = 0;
-
-  /* Reinitialize the buffer to create the sequence. */
-  err = ksba_writer_set_mem (writer, 1024);
-  if (err)
-    goto leave;
-
-  /* Calulate lengths. */
-  n  = _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
-  n += oidlen;
-  if (algoparmseq_len)
-    {
-      n += algoparmseq_len;
-    }
-  else if (pkalgo == PKALGO_ECC)
-    {
-      n += _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL,
-                               0, curve_oidlen);
-      n += curve_oidlen;
-    }
-  else if (pkalgo == PKALGO_RSA)
-    {
-      n += _ksba_ber_count_tl (TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
-    }
-
-  /* Write the sequence.  */
-  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
-  if (err)
-    goto leave;
-
-  /* Write the object id.  */
-  err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
-  if (!err)
-    err = ksba_writer_write (writer, oid, oidlen);
-  if (err)
-    goto leave;
-
-  /* Write the parameters. */
-  if (algoparmseq_len)
-    {
-      err = ksba_writer_write (writer, algoparmseq_value, algoparmseq_len);
-    }
-  else if (pkalgo == PKALGO_ECC)
-    {
-      /* We only support the namedCuve choice for ECC parameters.  */
-      err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL,
-                                0, curve_oidlen);
-      if (!err)
-        err = ksba_writer_write (writer, curve_oid, curve_oidlen);
-    }
-  else if (pkalgo == PKALGO_RSA)
-    {
-      err = _ksba_ber_write_tl (writer, TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
-    }
-  if (err)
-    goto leave;
-
-  /* Get the result. */
-  *r_der = ksba_writer_snatch_mem (writer, r_derlen);
-  if (!*r_der)
-    err = gpg_error (GPG_ERR_ENOMEM);
-
- leave:
-  ksba_writer_release (writer);
-  xfree (curve_oid);
-  return err;
+  return cryptval_from_sexp (1, sexp, r_der, r_derlen);
 }
 
 
-- 
1.8.5.2




More information about the Gnupg-devel mailing list