[svn] ksba - r268 - in trunk: . src tests tests/samples

svn author wk cvs at cvs.gnupg.org
Fri Apr 6 14:58:08 CEST 2007


Author: wk
Date: 2007-04-06 14:58:07 +0200 (Fri, 06 Apr 2007)
New Revision: 268

Added:
   trunk/tests/samples/openssl-secp256r1ca.cert.crt
   trunk/tests/samples/secp256r1-sha384_cert.crt
   trunk/tests/samples/secp256r1-sha512_cert.crt
   trunk/tests/samples/secp384r1-sha512_cert.crt
Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/configure.ac
   trunk/src/ChangeLog
   trunk/src/convert.h
   trunk/src/keyinfo.c
   trunk/src/oid.c
   trunk/tests/cert-basic.c
   trunk/tests/samples/README
Log:
First steps towards ECC integration.
cert-basic is at least able to parse the new sample certs.


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-01-30 20:11:15 UTC (rev 267)
+++ trunk/ChangeLog	2007-04-06 12:58:07 UTC (rev 268)
@@ -1,3 +1,7 @@
+2007-04-06  Werner Koch  <wk at g10code.com>
+
+	* configure.ac: Require libgpg-error 1.4.
+
 2006-11-29  Werner Koch  <wk at g10code.com>
 
 	Released 1.0.1.

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2007-01-30 20:11:15 UTC (rev 267)
+++ trunk/NEWS	2007-04-06 12:58:07 UTC (rev 268)
@@ -1,7 +1,7 @@
 Noteworthy changes in version 1.0.2
 ------------------------------------------------
  
- * Support for SHA-1.
+ * Support for SHA-2.
 
  * Fixed a couple of memory leaks.
 

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2007-01-30 20:11:15 UTC (rev 267)
+++ trunk/configure.ac	2007-04-06 12:58:07 UTC (rev 268)
@@ -47,7 +47,7 @@
 KSBA_CONFIG_API_VERSION=1
 
 
-NEED_GPG_ERROR_VERSION=1.2
+NEED_GPG_ERROR_VERSION=1.4
 
 
 PACKAGE=$PACKAGE_NAME

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2007-01-30 20:11:15 UTC (rev 267)
+++ trunk/src/ChangeLog	2007-04-06 12:58:07 UTC (rev 268)
@@ -1,3 +1,13 @@
+2007-04-06  Werner Koch  <wk at g10code.com>
+
+	* keyinfo.c (curve_names): New.
+	(get_ecc_curve_oid): New.
+	(_ksba_keyinfo_from_sexp): Support ECC.
+	(oid_from_buffer): Ditto.
+	(_ksba_keyinfo_to_sexp): Ditto.
+
+	* oid.c (_ksba_oid_from_buf): New.
+
 2007-01-30  Werner Koch  <wk at g10code.com>
 
 	* shared.h: Add constants for SHA-2.

Modified: trunk/src/convert.h
===================================================================
--- trunk/src/convert.h	2007-01-30 20:11:15 UTC (rev 267)
+++ trunk/src/convert.h	2007-04-06 12:58:07 UTC (rev 268)
@@ -42,6 +42,8 @@
 
 /*-- oid.c --*/
 char *_ksba_oid_node_to_str (const unsigned char *image, AsnNode node);
+gpg_error_t _ksba_oid_from_buf (const void *buffer, size_t buflen,
+                                unsigned char **rbuf, size_t *rlength);
 
 
 /*-- name.c --*/

Modified: trunk/src/keyinfo.c
===================================================================
--- trunk/src/keyinfo.c	2007-01-30 20:11:15 UTC (rev 267)
+++ trunk/src/keyinfo.c	2007-04-06 12:58:07 UTC (rev 268)
@@ -34,6 +34,7 @@
 #include "asn1-func.h"
 #include "keyinfo.h"
 #include "shared.h"
+#include "convert.h"
 #include "ber-help.h"
 
 struct algo_table_s {
@@ -41,6 +42,7 @@
   const unsigned char *oid;  /* NULL indicattes end of table */
   int                  oidlen;
   int supported;
+  int is_ecc;
   const char *algo_string;
   const char *elem_string; /* parameter name or '-' */
   const char *ctrl_string; /* expected tag values (value > 127 are raw data)*/
@@ -51,21 +53,31 @@
   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.1 */
     "1.2.840.113549.1.1.1", /* rsaEncryption (RSAES-PKCA1-v1.5) */ 
     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01", 9, 
-    1, "rsa", "-ne", "\x30\x02\x02" },
+    1, 0, "rsa", "-ne", "\x30\x02\x02" },
   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.7 */
     "1.2.840.113549.1.1.7", /* RSAES-OAEP */ 
     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x07", 9, 
-    0, "rsa", "-ne", "\x30\x02\x02"}, /* (patent problems) */
+    0, 0, "rsa", "-ne", "\x30\x02\x02"}, /* (patent problems) */
   { /* */
     "2.5.8.1.1", /* rsa (ambiguous due to missing padding rules)*/
     "\x55\x08\x01\x01", 4, 
-    1, "ambiguous-rsa", "-ne", "\x30\x02\x02" },
+    1, 0, "ambiguous-rsa", "-ne", "\x30\x02\x02" },
   { /* iso.member-body.us.x9-57.x9cm.1 */
     "1.2.840.10040.4.1", /*  dsa */
     "\x2a\x86\x48\xce\x38\x04\x01", 7, 
-    1, "dsa", "y", "\x02" }, 
+    1, 0, "dsa", "y", "\x02" }, 
   /* FIXME: Need code to extract p,q,g from the parameters */
+ 
+  { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha1 */
+    "1.2.840.10045.4.1", /*  ecdsa */
+    "\x2a\x86\x48\xce\x3d\x04\x01", 7, 
+    1, 1, "ecdsa", "q", "\x80" }, 
 
+  { /* iso.member-body.us.ansi-x9-62.2.1 */
+    "1.2.840.10045.2.1", /*  ecdsa or ecdh */
+    "\x2a\x86\x48\xce\x3d\x02\x01", 7, 
+    1, 1,"ecc", "q", "\x80" }, 
+
   {NULL}
 };
 
@@ -74,52 +86,52 @@
   {  /* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 */
     "1.2.840.113549.1.1.5", /* sha1WithRSAEncryption */ 
     "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05", 9, 
-    1, "rsa", "s", "\x82", GCRY_MD_SHA1 },
+    1, 0, "rsa", "s", "\x82", GCRY_MD_SHA1 },
   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 */
     "1.2.840.113549.1.1.4", /* md5WithRSAEncryption */ 
     "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04", 9, 
-    1, "rsa", "s", "\x82", GCRY_MD_MD5 },
+    1, 0, "rsa", "s", "\x82", GCRY_MD_MD5 },
   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.2 */
     "1.2.840.113549.1.1.2", /* md2WithRSAEncryption */ 
     "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02", 9, 
-    0, "rsa", "s", "\x82", 0 },
+    0, 0, "rsa", "s", "\x82", 0 },
   { /* iso.member-body.us.x9-57.x9cm.3 */
     "1.2.840.10040.4.3", /*  dsaWithSha1 */
     "\x2a\x86\x48\xce\x38\x04\x03", 7, 
-    1, "dsa", "-rs", "\x30\x02\x02", GCRY_MD_SHA1 }, 
+    1, 0, "dsa", "-rs", "\x30\x02\x02", GCRY_MD_SHA1 }, 
   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.1 */
     "1.2.840.113549.1.1.1", /* rsaEncryption used without hash algo*/ 
     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01", 9, 
-    1, "rsa", "s", "\x82" },
+    1, 0, "rsa", "s", "\x82" },
   { /* from NIST's OIW - actually belongs in a pure hash table */
     "1.3.14.3.2.26",  /* sha1 */
     "\x2B\x0E\x03\x02\x1A", 5,
-    0, "sha-1", "", "", GCRY_MD_SHA1 },
+    0, 0, "sha-1", "", "", GCRY_MD_SHA1 },
 
   { /* As used by telesec cards */
     "1.3.36.3.3.1.2",  /* rsaSignatureWithripemd160 */
     "\x2b\x24\x03\x03\x01\x02", 6,
-    1, "rsa", "s", "\x82", GCRY_MD_RMD160 },
+    1, 0, "rsa", "s", "\x82", GCRY_MD_RMD160 },
 
   { /* from NIST's OIW - used by TU Darmstadt */
     "1.3.14.3.2.29",  /* sha-1WithRSAEncryption */
     "\x2B\x0E\x03\x02\x1D", 5,
-    1, "rsa", "s", "\x82", GCRY_MD_SHA1 },
+    1, 0, "rsa", "s", "\x82", GCRY_MD_SHA1 },
 
   { /* from PKCS#1  */
     "1.2.840.113549.1.1.11", /* sha256WithRSAEncryption */
     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b", 9,
-    1, "rsa", "s", "\x82", GCRY_MD_SHA256 },
+    1, 0, "rsa", "s", "\x82", GCRY_MD_SHA256 },
 
   { /* from PKCS#1  */
     "1.2.840.113549.1.1.12", /* sha384WithRSAEncryption */
     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0c", 9,
-    1, "rsa", "s", "\x82", GCRY_MD_SHA384 },
+    1, 0, "rsa", "s", "\x82", GCRY_MD_SHA384 },
 
   { /* from PKCS#1  */
     "1.2.840.113549.1.1.13", /* sha512WithRSAEncryption */
     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0d", 9,
-    1, "rsa", "s", "\x82", GCRY_MD_SHA512 },
+    1, 0, "rsa", "s", "\x82", GCRY_MD_SHA512 },
 
   {NULL}
 };
@@ -128,11 +140,34 @@
   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.1 */
     "1.2.840.113549.1.1.1", /* rsaEncryption (RSAES-PKCA1-v1.5) */ 
     "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01", 9, 
-    1, "rsa", "a", "\x82" },
+    1, 0, "rsa", "a", "\x82" },
   {NULL}
 };
 
 
+/* This tables maps names of ECC curves names to OIDs.  A similar
+   table is used by lib gcrypt.  */
+static const struct
+{
+  const char *oid; 
+  const char *name; 
+} curve_names[] = 
+  {
+    { "1.2.840.10045.3.1.1", "NIST P-192" },
+    { "1.2.840.10045.3.1.1", "prime192v1" }, 
+    { "1.2.840.10045.3.1.1", "secp192r1"  },
+
+    { "1.2.840.10045.3.1.7", "NIST P-256", }, 
+    { "1.2.840.10045.3.1.7", "prime256v1" },          
+    { "1.2.840.10045.3.1.7", "secp256r1"  },          
+
+    { NULL, NULL}
+  };
+
+
+
+
+
 struct stringbuf {
   size_t len;
   size_t size;
@@ -170,6 +205,60 @@
 } while (0)
 
 
+#if 0
+static void
+dump_hex (const unsigned char *p, size_t n)
+{
+  if (!p)
+    fputs (" none", stderr);
+  else
+    {
+      for (; n; n--, p++)
+        fprintf (stderr, " %02X", *p);
+    }
+}
+#endif
+
+
+/* Given a string BUF of length BUFLEN with either the name of an ECC
+   curve or its OID in dotted form return the DER encoding of the OID.
+   The caller must free the result.  On error NULL is returned.  */
+static unsigned char *
+get_ecc_curve_oid (const unsigned char *buf, size_t buflen, size_t *r_oidlen)
+{
+  unsigned char *der_oid;
+
+  /* Skip an optional "oid." prefix. */
+  if (buflen > 4 && buf[3] == '.' && digitp (buf+4)
+      && ((buf[0] == 'o' && buf[1] == 'i' && buf[2] == 'd')
+          ||(buf[0] == 'O' && buf[1] == 'I' && buf[2] == 'D')))
+    {
+      buf += 4;
+      buflen -= 4;
+    }
+
+  /* If it does not look like an OID - map it through the table.  */
+  if (buflen && !digitp (buf))
+    {
+      int i;
+
+      for (i=0; curve_names[i].oid; i++)
+        if (buflen == strlen (curve_names[i].name)
+            && !memcmp (buf, curve_names[i].name, buflen))
+          break;
+      if (curve_names[i].oid)
+        return NULL; /* Not found.  */
+      buf = curve_names[i].name;
+      buflen = strlen (curve_names[i].name);
+    }
+
+  if (_ksba_oid_from_buf (buf, buflen, &der_oid, r_oidlen))
+    return NULL;
+  return der_oid;
+}
+
+
+
 /* Return the OFF and the LEN of algorithm within DER.  Do some checks
    and return the number of bytes read in r_nread, adding this to der
    does point into the BIT STRING.
@@ -181,7 +270,7 @@
 static gpg_error_t
 get_algorithm (int mode, const unsigned char *der, size_t derlen,
                size_t *r_nread, size_t *r_pos, size_t *r_len, int *r_bitstr,
-               size_t *r_parm_pos, size_t *r_parm_len)
+               size_t *r_parm_pos, size_t *r_parm_len, int *r_parm_type)
 {
   int c;
   const unsigned char *start = der;
@@ -219,7 +308,7 @@
   derlen -= len;
   seqlen -= der - startseq;;
 
-  /* check that the parameter is NULL or not there */
+  /* Parse the parameter.  */
   if (seqlen)
     {
       const unsigned char *startparm = der;
@@ -229,16 +318,20 @@
       c = *der++; derlen--;
       if ( c == 0x05 ) 
         {
-          /*printf ("parameter: NULL \n"); the only correct thing */
+          /*printf ("parameter: NULL \n"); the usual case */
           if (!derlen)
             return gpg_error (GPG_ERR_INV_KEYINFO);
           c = *der++; derlen--;
           if (c) 
-            return gpg_error (GPG_ERR_BAD_BER);  /* NULL must have a length of 0 */
+            return gpg_error (GPG_ERR_BAD_BER);  /* NULL must have a
+                                                    length of 0 */
           seqlen -= 2;
         }
       else if (r_parm_pos && r_parm_len && c == 0x04)
-        { /* this is an octet string parameter and we need it */
+        { 
+          /*  This is an octet string parameter and we need it.  */
+          if (r_parm_type)
+            *r_parm_type = TYPE_OCTET_STRING;
           TLV_LENGTH();
           *r_parm_pos = der - start;
           *r_parm_len = len;
@@ -247,6 +340,19 @@
           derlen -= len;
           seqlen -= len;
         }
+      else if (r_parm_pos && r_parm_len && c == 0x06)
+        { 
+          /*  This is an object identifier.  */
+          if (r_parm_type)
+            *r_parm_type = TYPE_OBJECT_ID;
+          TLV_LENGTH();
+          *r_parm_pos = der - start;
+          *r_parm_len = len;
+          seqlen -= der - startparm;
+          der += len;
+          derlen -= len;
+          seqlen -= len;
+        }
       else
         {
 /*            printf ("parameter: with tag %02x - ignored\n", c); */
@@ -296,7 +402,7 @@
   *r_oid = NULL;
   *r_nread = 0;
   err = get_algorithm (0, der, derlen, &nread, &off, &len, &is_bitstr,
-                       NULL, NULL);
+                       NULL, NULL, NULL);
   if (err)
     return err;
   *r_nread = nread;
@@ -319,7 +425,7 @@
   *r_nread = 0;
   off2 = len2 = 0;
   err = get_algorithm (0, der, derlen, &nread, &off, &len, &is_bitstr,
-                       &off2, &len2);
+                       &off2, &len2, NULL);
   if (err)
     return err;
   *r_nread = nread;
@@ -450,7 +556,9 @@
 {
   gpg_error_t err;
   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 *ctrl;
@@ -468,7 +576,7 @@
   TLV_LENGTH();
   /* and now the inner part */
   err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr,
-                       NULL, NULL);
+                       &parm_off, &parm_len, &parm_type);
   if (err)
     return err;
   
@@ -484,6 +592,10 @@
   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);
+
   der += nread;
   derlen -= nread;
 
@@ -492,7 +604,10 @@
          CMS as an octet string - for ease of implementation we always
          allow both */
       if (!derlen)
-        return gpg_error (GPG_ERR_INV_KEYINFO);
+        {
+          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");
@@ -508,6 +623,15 @@
      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].is_ecc && parm_oid)
+    {
+      put_stringbuf (&sb, "(");
+      put_stringbuf_sexp (&sb, "curve");
+      put_stringbuf_sexp (&sb, parm_oid);
+      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; 
@@ -516,15 +640,30 @@
     {
       int is_int;
 
-      if (!derlen)
-        return gpg_error (GPG_ERR_INV_KEYINFO);
-      c = *der++; derlen--;
-      if ( c != *ctrl )
-        return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not the required tag */
-      is_int = c == 0x02;
-      TLV_LENGTH ();
-      if (is_int && *elem != '-')
-        { /* take this integer */
+      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 ();
+        }
+      if (is_int && *elem != '-')  /* Take this integer.  */
+        { 
           char tmp[2];
 
           put_stringbuf (&sb, "(");
@@ -537,7 +676,8 @@
         }
     }
   put_stringbuf (&sb, "))");
-  
+  xfree (parm_oid);
+
   *r_string = get_stringbuf (&sb);
   if (!*r_string)
     return gpg_error (GPG_ERR_ENOMEM);
@@ -546,14 +686,16 @@
 }
 
 
-/* match the algorithm string given in BUF which is of length BUFLEN
+/* Match the algorithm string given in BUF which is of length BUFLEN
    with the known algorithms from our table and returns the table
    entries for the DER encoded OID.
 
-   FIXME: We restrict this for now to RSA because the code using this
-   function is not yet prepared to handle other algorithms */
+   FIXME: We restrict this for now to RSA and ECC because the code
+   using this function is not yet prepared to handle other
+   algorithms.  */
 static const unsigned char *
-oid_from_buffer (const unsigned char *buf, int buflen, int *oidlen)
+oid_from_buffer (const unsigned char *buf, int buflen, int *oidlen,
+                 int *r_is_ecc)
 {
   int i;
 
@@ -581,8 +723,11 @@
   if (!pk_algo_table[i].oid)
     return NULL;
   
-  if (strcmp (pk_algo_table[i].elem_string, "-ne"))
-    return NULL; /* that is not RSA - we can't handle it yet */
+  if (!pk_algo_table[i].is_ecc
+      && strcmp (pk_algo_table[i].elem_string, "-ne"))
+    return NULL; /* Not ECC or RSA - we can't handle it yet.  */
+
+  *r_is_ecc = pk_algo_table[i].is_ecc;
   *oidlen = pk_algo_table[i].oidlen;
   return pk_algo_table[i].oid;
 }
@@ -600,6 +745,9 @@
   unsigned long n, n1;
   const unsigned char *oid;
   int oidlen;
+  unsigned char *curve_oid = NULL;
+  size_t curve_oidlen;
+  int is_ecc;
   int i;
   struct {
     const char *name;
@@ -611,7 +759,7 @@
   ksba_writer_t writer = NULL;
   void *bitstr_value = NULL;
   size_t bitstr_len;
-    
+  int ecc_curve_idx, ecc_q_idx;  
 
   if (!sexp)
     return gpg_error (GPG_ERR_INV_VALUE);
@@ -633,13 +781,13 @@
     return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP);
   s++;
 
-  /* break out the algorithm ID */
+  /* 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);
+  oid = oid_from_buffer (s, n, &oidlen, &is_ecc);
   if (!oid)
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
   s += n;
@@ -661,7 +809,7 @@
       parm[parmidx].namelen = n;
       s += n; 
       if (!digitp(s))
-        return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* but may also be an invalid one */
+        return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
 
       n = strtoul (s, &endp, 10);
       s = endp;
@@ -672,127 +820,195 @@
       parm[parmidx].valuelen = n;
       s += n;
       if ( *s != ')')
-        return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* but may also be an invalid one */
+        return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
       s++;
     }
   s++;
-  /* we need another closing parenthesis */
+  /* We need another closing parenthesis. */
   if ( *s != ')' )
     return gpg_error (GPG_ERR_INV_SEXP); 
 
-  /* check that the names match the requirements for RSA */
-  s = "ne"; 
-  if (parmidx != strlen (s))
-    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
-  for (i=0; i < parmidx; i++)
+  ecc_q_idx = ecc_curve_idx = -1;
+  if (is_ecc)
     {
-      if (parm[i].namelen != 1 || parm[i].name[0] != s[i])
+      for (i=0; i < parmidx; i++)
+        {
+          if (ecc_curve_idx == -1 
+              && parm[i].namelen == 5 && !memcmp (parm[i].name, "curve", 5))
+            ecc_curve_idx = i;
+          else if (ecc_q_idx == -1 
+              && parm[i].namelen == 1 && parm[i].name[0] == 'q')
+            ecc_q_idx = i;
+        }
+      if (ecc_curve_idx == -1 || ecc_q_idx == -1)
         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+
+      curve_oid = get_ecc_curve_oid (parm[ecc_curve_idx].value,
+                                     parm[ecc_curve_idx].valuelen,
+                                     &curve_oidlen);
+      if (!curve_oid)
+        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     }
-
-  
-  /* Create write object.  We create the keyinfo in 2 steps: 1. we
-     build the inner one and encapsulate it in bit string. 2. we
-     create the outer sequence include the algorithm identifier and
-     the bit string from step 1 */
+  else /* This is RSA.  */
+    {
+      /* Check that the names match the requirements for RSA */
+      s = "ne"; 
+      if (parmidx != strlen (s))
+        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+      for (i=0; i < parmidx; i++)
+        {
+          if (parm[i].namelen != 1 || parm[i].name[0] != s[i])
+            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;
+  
+  if (is_ecc)
+    {
+      /* Write the bit string header and the number of unused bits. */
+      err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL, 
+                                0, parm[ecc_q_idx].valuelen + 1);
+      if (!err)
+        err = ksba_writer_write (writer, "", 1);
+      /* And the actual raw value.  */
+      if (!err)
+        err = ksba_writer_write (writer, parm[ecc_q_idx].value,
+                                 parm[ecc_q_idx].valuelen);
+      if (err)
+        goto leave;
 
-  /* calculate the size of the sequence value and the size of the
-     bit string value */
-  for (n=0, i=0; i < parmidx; i++ )
+    }
+  else /* RSA */
     {
-      n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
-                                parm[i].valuelen);
-      n += parm[i].valuelen;
-    }
-  
-  n1 = 1; /* # of unused bits */
-  n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
-  n1 += n;
+      /* For RSA we create the keyinfo in 2 steps:
 
-  /* 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;
+        1. We build the inner one and encapsulate it in bit string.
+        
+        2. We create the outer sequence include the algorithm identifier
+           and the bit string from step 1.  
+      */
+
+      /* Calculate the size of the sequence value and the size of the bit
+         string value */
+      for (n=0, i=0; i < parmidx; i++ )
+        {
+          n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
+                                   parm[i].valuelen);
+          n += parm[i].valuelen;
+        }
   
-  /* write the sequence tag and the integers */
-  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
-  if (err)
-    goto leave;
-  for (i=0; i < parmidx; 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[i].valuelen);
+      n1 = 1; /* # of unused bits.  */
+      n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
+      n1 += n;
+  
+      /* 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[i].value, parm[i].valuelen);
+        err = ksba_writer_write (writer, "", 1);
       if (err)
         goto leave;
+      
+      /* Write the sequence tag and the integers. */
+      err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
+      if (err)
+        goto leave;
+      for (i=0; i < parmidx; 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[i].valuelen);
+          if (!err)
+            err = ksba_writer_write (writer, parm[i].value, parm[i].valuelen);
+          if (err)
+            goto leave;
+        }
     }
 
-  /* get the encoded bit string */
+  /* 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;
     }
-  /* reinitialize the buffer to create the outer sequence */
+  /* Reinitialize the buffer to create the outer sequence. */
   err = ksba_writer_set_mem (writer, 1024);
   if (err)
     goto leave;
 
-  /* calulate lengths */
+  /* Calulate lengths. */
   n  = _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
   n += oidlen;
-  n += _ksba_ber_count_tl (TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
-  
+  if (is_ecc)
+    {
+      n += _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL,
+                               0, curve_oidlen);
+      n += curve_oidlen;
+    }
+  else
+    {
+      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;
 
-  /* the outer sequence */
+  /* The outer sequence.  */
   err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n1);
   if (err)
     goto leave;
 
-  /* the sequence */
+  /* The sequence.  */
   err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
   if (err)
     goto leave;
 
-  /* the object id */
+  /* 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;
-  /* the parameter */
-  err = _ksba_ber_write_tl (writer, TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
+
+  /* The parameter. */
+  if (is_ecc)
+    {
+      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 /* RSA */
+    {
+      err = _ksba_ber_write_tl (writer, TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
+    }
   if (err)
     goto leave;
 
-  /* append the pre-constructed bit string */
+  /* Append the pre-constructed bit string.  */
   err = ksba_writer_write (writer, bitstr_value, bitstr_len);
   if (err)
     goto leave;
   
-  /* and get the result */
+  /* Get the result. */
   *r_der = ksba_writer_snatch_mem (writer, r_derlen);
   if (!*r_der)
-      err = gpg_error (GPG_ERR_ENOMEM);
+    err = gpg_error (GPG_ERR_ENOMEM);
 
  leave:
   ksba_writer_release (writer);
   xfree (bitstr_value);
+  xfree (curve_oid);
   return err;
 }
 
@@ -824,7 +1040,7 @@
   
 
   err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr,
-                       NULL, NULL);
+                       NULL, NULL, NULL);
   if (err)
     return err;
   

Modified: trunk/src/oid.c
===================================================================
--- trunk/src/oid.c	2007-01-30 20:11:15 UTC (rev 267)
+++ trunk/src/oid.c	2007-04-06 12:58:07 UTC (rev 268)
@@ -237,9 +237,28 @@
 }
 
 
+/* Convert the string in BUFFER which is of length BUFLEN to its DER
+   encoding and returns it in a new allocated buffer RBUF and its
+   length in RLENGTH.  RBUF is set to NULL if an error is returned.
+   The caller must free the returned buffer using ksba_free() or the
+   function he has registered as a replacement.  */
+gpg_error_t
+_ksba_oid_from_buf (const void *buffer, size_t buflen,
+                    unsigned char **rbuf, size_t *rlength)
+{
+  gpg_error_t err;
+  char *string;
 
-
-
-
-
-
+  string = xtrymalloc (buflen+1);
+  if (!string)
+    {
+      *rbuf = NULL;
+      *rlength = 0;
+      return gpg_error_from_syserror ();
+    }
+  memcpy (string, buffer, buflen);
+  string[buflen] = 0;
+  err = ksba_oid_from_str (string, rbuf, rlength);
+  xfree (string);
+  return err;
+}

Modified: trunk/tests/cert-basic.c
===================================================================
--- trunk/tests/cert-basic.c	2007-01-30 20:11:15 UTC (rev 267)
+++ trunk/tests/cert-basic.c	2007-04-06 12:58:07 UTC (rev 268)
@@ -97,6 +97,7 @@
           else if (*p == ')')
             {
               putchar (*p);
+              p++;
               if (--level <= 0 )
                 return;
             }
@@ -108,7 +109,8 @@
           else
             {
               char *endp;
-              unsigned long n;
+              unsigned long n, i;
+              int need_hex;
 
               n = strtoul (p, &endp, 10);
               p = endp;
@@ -117,10 +119,33 @@
                   fputs ("[invalid s-exp]", stdout);
                   return;
                 }
-              putchar('#');
-              for (p++; n; n--, p++)
-                printf ("%02X", *p);
-              putchar('#');
+              p++;
+              for (i=0; i < n; i++)
+                if ( !((p[i] >='A' && p[i] <= 'Z')
+                       || (p[i] >='a' && p[i] <='z')
+                       || (p[i] >='0' && p[i] <='9')
+                       || p[i] == '-'
+                       || p[i] == '.'))
+                  break;
+              need_hex = (i<n);
+              if (!n /* n==0 is not allowed, but anyway.  */
+                  || (!need_hex 
+                      && !((*p >='A' && *p <= 'Z') || (*p >='a' && *p <='z'))))
+                printf ("%lu:", n);
+
+              if (need_hex)
+                {
+                  putchar('#');
+                  for (; n; n--, p++)
+                    printf ("%02X", *p);
+                  putchar('#');
+                }
+              else
+                {
+                  for (; n; n--, p++)
+                    putchar (*p);
+                }
+              putchar(' ');
             }
         }
     }

Modified: trunk/tests/samples/README
===================================================================
--- trunk/tests/samples/README	2007-01-30 20:11:15 UTC (rev 267)
+++ trunk/tests/samples/README	2007-04-06 12:58:07 UTC (rev 268)
@@ -38,5 +38,16 @@
  ov2-user.crt           User certificate
  ov2-userrev.crt        A user certificate revoked by OCSP
 
+Certificates downloaded on 2007-04-05 from
+http://dev.experimentalstuff.com:8082/CIC_sample-certs_2006-06-22.zip
+and converted to binary format.  These are signed with
+ECDSA-P256-SHA384, ECDSA-P256-SHA512, and ECDSA-P384-SHA512.
 
+ secp256r1-sha384_cert.crt 
+ secp256r1-sha512_cert.crt
+ secp384r1-sha512_cert.crt
 
+From http://dev.experimentalstuff.com:8082/certs/secp256r1ca.cert.pem
+
+ openssl-secp256r1ca.cert.crt
+

Added: trunk/tests/samples/openssl-secp256r1ca.cert.crt
===================================================================
(Binary files differ)


Property changes on: trunk/tests/samples/openssl-secp256r1ca.cert.crt
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/tests/samples/secp256r1-sha384_cert.crt
===================================================================
(Binary files differ)


Property changes on: trunk/tests/samples/secp256r1-sha384_cert.crt
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/tests/samples/secp256r1-sha512_cert.crt
===================================================================
(Binary files differ)


Property changes on: trunk/tests/samples/secp256r1-sha512_cert.crt
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/tests/samples/secp384r1-sha512_cert.crt
===================================================================
(Binary files differ)


Property changes on: trunk/tests/samples/secp384r1-sha512_cert.crt
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream




More information about the Gnupg-commits mailing list