]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added gnutls_x509_crq_set_key_purpose_oid and gnutls_x509_crq_get_key_purpose_oid.
authorNikos Mavrogiannopoulos <nmav@crystal.(none)>
Sat, 4 Oct 2008 08:37:42 +0000 (11:37 +0300)
committerNikos Mavrogiannopoulos <nmav@crystal.(none)>
Sat, 4 Oct 2008 08:37:42 +0000 (11:37 +0300)
NEWS
includes/gnutls/x509.h
lib/x509/crq.c
lib/x509/extensions.c
lib/x509/output.c
src/certtool.c

diff --git a/NEWS b/NEWS
index 3b3cbe99e47c50188382163209da251c37b99486..0c65d5a91064a9c26e0bd868f16389091a6f3aa2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,8 @@ gnutls_x509_crq_get_subject_alt_othername_oid: ADDED
 gnutls_x509_crq_set_basic_constraints: ADDED
 gnutls_x509_crq_set_key_usage: ADDED
 gnutls_x509_crq_set_subject_alt_name: ADDED
+gnutls_x509_crq_set_key_purpose_oid: ADDED
+gnutls_x509_crq_get_key_purpose_oid: ADDED
 
 * Version 2.5.9 (released 2008-09-29)
 
index ee6e937cb44fc41184ddc447bda3097fc016de85..aaee2d562933581c4c7dc8335cf2fba765fbefa2 100644 (file)
@@ -717,6 +717,11 @@ extern "C"
   int gnutls_x509_crq_set_key_usage (gnutls_x509_crq_t crq, unsigned int usage);
   int gnutls_x509_crq_set_basic_constraints (gnutls_x509_crq_t crq,
                                       unsigned int ca, int pathLenConstraint);
+  int gnutls_x509_crq_set_key_purpose_oid (gnutls_x509_crq_t cert,
+                                    const void *oid, unsigned int critical);
+  int gnutls_x509_crq_get_key_purpose_oid (gnutls_x509_crq_t cert,
+                                    int indx, void *oid, size_t * sizeof_oid,
+                                    unsigned int *critical);
 
   int gnutls_x509_crq_get_extension_data (gnutls_x509_crq_t cert, int indx,
                                    void *data, size_t * sizeof_data);
index 0db1b370c8e5a623ae01f246abf5bafdbecce979..df8de478ba2d43d2f372be821fc31429a0608831 100644 (file)
@@ -524,6 +524,7 @@ overwrite_attribute (ASN1_TYPE asn, const char* root, unsigned int indx,
       return result;
     }
 
+
   return 0;
 }
 
@@ -626,7 +627,7 @@ gnutls_x509_crq_set_attribute_by_oid (gnutls_x509_crq_t crq,
                                      size_t sizeof_buf)
 {
   int result;
-  gnutls_datum data = {buf, sizeof_buf};
+  gnutls_datum data = { buf, sizeof_buf };
 
   if (crq == NULL)
     {
@@ -1361,7 +1362,6 @@ gnutls_x509_crq_get_extension_info (gnutls_x509_crq_t cert, int indx,
   if (result == ASN1_ELEMENT_NOT_FOUND)
     {
       asn1_delete_structure (&c2);
-      gnutls_assert();
       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     }
   else if (result < 0)
@@ -1963,4 +1963,233 @@ gnutls_x509_crq_set_key_usage (gnutls_x509_crq_t crq, unsigned int usage)
   return 0;
 }
 
+/**
+  * gnutls_x509_crq_get_key_purpose_oid - This function returns the Certificate's key purpose OIDs
+  * @cert: should contain a #gnutls_x509_crq_t structure
+  * @indx: This specifies which OID to return. Use zero to get the first one.
+  * @oid: a pointer to a buffer to hold the OID (may be null)
+  * @sizeof_oid: initially holds the size of @oid
+  *
+  * This function will extract the key purpose OIDs of the Certificate
+  * specified by the given index. These are stored in the Extended Key
+  * Usage extension (2.5.29.37) See the GNUTLS_KP_* definitions for
+  * human readable names.
+  *
+  * If @oid is null then only the size will be filled.
+  *
+  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
+  * not long enough, and in that case the *sizeof_oid will be updated
+  * with the required size.  On success 0 is returned.
+  **/
+int
+gnutls_x509_crq_get_key_purpose_oid (gnutls_x509_crq_t cert,
+                                    int indx, void *oid, size_t * sizeof_oid,
+                                    unsigned int *critical)
+{
+  char tmpstr[MAX_NAME_SIZE];
+  int result, len;
+  gnutls_datum_t prev_data;
+  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+  opaque tmp[MAX_CRQ_EXTENSIONS_SIZE];
+  size_t tmp_size;
+
+  if (cert == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  if (oid)
+    memset (oid, 0, *sizeof_oid);
+  else
+    *sizeof_oid = 0;
+
+  tmp_size = sizeof(tmp);
+  result = gnutls_x509_crq_get_extension_by_oid (cert, "2.5.29.37", 0,
+                                              tmp, &tmp_size, critical);
+
+  if (result < 0 && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+    {
+      gnutls_assert();
+      return result;
+    }
+
+  if (result < 0)
+    {
+      prev_data.data = NULL;
+      prev_data.size = 0;
+    }
+  else
+    {
+      prev_data.data = tmp;
+      prev_data.size = tmp_size;
+    }
+
+  result = asn1_create_element
+    (_gnutls_get_pkix (), "PKIX1.ExtKeyUsageSyntax", &c2);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+
+  if ( prev_data.size > 0)
+    {
+      result = asn1_der_decoding (&c2, prev_data.data, prev_data.size, NULL);
+      if (result != ASN1_SUCCESS)
+        {
+          gnutls_assert ();
+          asn1_delete_structure (&c2);
+          return _gnutls_asn2err (result);
+        }
+    }
+
+  indx++;
+  /* create a string like "?1"
+   */
+  snprintf (tmpstr, sizeof (tmpstr), "?%u", indx);
+
+  len = *sizeof_oid;
+  result = asn1_read_value (c2, tmpstr, oid, &len);
+
+  *sizeof_oid = len;
+  asn1_delete_structure (&c2);
+
+  if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND)
+    {
+      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+    }
+
+  if (result != ASN1_SUCCESS)
+    {
+      if (result != ASN1_MEM_ERROR)
+        gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  return 0;
+
+}
+
+/**
+ * gnutls_x509_crq_set_key_purpose_oid - Sets the Certificate's key purpose OIDs
+ * @cert: a certificate of type #gnutls_x509_crq_t
+ * @oid: a pointer to a null terminated string that holds the OID
+ * @critical: Whether this extension will be critical or not
+ *
+ * This function will set the key purpose OIDs of the Certificate.
+ * These are stored in the Extended Key Usage extension (2.5.29.37)
+ * See the GNUTLS_KP_* definitions for human readable names.
+ *
+ * Subsequent calls to this function will append OIDs to the OID list.
+ *
+ * On success 0 is returned.
+ **/
+int
+gnutls_x509_crq_set_key_purpose_oid (gnutls_x509_crq_t cert,
+                                    const void *oid, unsigned int critical)
+{
+  int result;
+  gnutls_datum_t prev_data, der_data;
+  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+  opaque tmp[MAX_CRQ_EXTENSIONS_SIZE];
+  size_t tmp_size;
+
+  if (cert == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  /* Check if the extension already exists.
+   */
+  tmp_size = sizeof(tmp);
+  result = gnutls_x509_crq_get_extension_by_oid (cert, "2.5.29.37", 0,
+                                              tmp, &tmp_size, NULL);
+
+  if (result < 0 && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+    {
+      gnutls_assert();
+      return result;
+    }
+
+  if (result < 0)
+    {
+      prev_data.data = NULL;
+      prev_data.size = 0;
+    }
+  else
+    {
+      prev_data.data = tmp;
+      prev_data.size = tmp_size;
+    }
+
+  result = asn1_create_element
+    (_gnutls_get_pkix (), "PKIX1.ExtKeyUsageSyntax", &c2);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  if (prev_data.size > 0)
+    {
+      /* decode it.
+       */
+      result = asn1_der_decoding (&c2, prev_data.data, prev_data.size, NULL);
+
+      if (result != ASN1_SUCCESS)
+       {
+         gnutls_assert ();
+         asn1_delete_structure (&c2);
+         return _gnutls_asn2err (result);
+       }
+
+    }
+
+  /* generate the extension.
+   */
+  /* 1. create a new element.
+   */
+  result = asn1_write_value (c2, "", "NEW", 1);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&c2);
+      return _gnutls_asn2err (result);
+    }
+
+  /* 2. Add the OID.
+   */
+  result = asn1_write_value (c2, "?LAST", oid, 1);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&c2);
+      return _gnutls_asn2err (result);
+    }
+
+  result = _gnutls_x509_der_encode (c2, "", &der_data, 0);
+  asn1_delete_structure (&c2);
+
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  result = _gnutls_x509_crq_set_extension (cert, "2.5.29.37",
+                                          &der_data, critical);
+
+  _gnutls_free_datum (&der_data);
+
+
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return result;
+    }
+}
+
 #endif /* ENABLE_PKI */
index 81ba84bef3e5f7067479793e1d0a7c67e4be0338..51b97abedd969b65af87355eb4261bc65a9f738d 100644 (file)
@@ -582,8 +582,6 @@ _gnutls_x509_crq_set_extension (gnutls_x509_crq_t crq,
 
   result = gnutls_x509_crq_set_attribute_by_oid (crq, "1.2.840.113549.1.9.14",
                                      der.data, der.size);
-                                     
-  _gnutls_free_datum( &der);
 
   if (result < 0)
     {
index 4451421484a846725db46f6dfbaf6120c7d5a25e..69eb7ef50b82d2db458ea035d211f516db67af95 100644 (file)
@@ -372,7 +372,7 @@ print_crldist (gnutls_string * str, gnutls_x509_crt_t cert)
 }
 
 static void
-print_key_purpose (gnutls_string * str, gnutls_x509_crt_t cert)
+print_key_purpose (gnutls_string * str, const char* prefix, int type, void* cert)
 {
   int indx;
   char *buffer = NULL;
@@ -382,8 +382,13 @@ print_key_purpose (gnutls_string * str, gnutls_x509_crt_t cert)
   for (indx = 0;; indx++)
     {
       size = 0;
-      err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer,
+      if (type == TYPE_CRT)
+        err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer,
+                                                &size, NULL);
+      else
+        err = gnutls_x509_crq_get_key_purpose_oid (cert, indx, buffer,
                                                 &size, NULL);
+
       if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
        return;
       if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
@@ -400,8 +405,13 @@ print_key_purpose (gnutls_string * str, gnutls_x509_crt_t cert)
          return;
        }
 
-      err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer,
+      if (type == TYPE_CRT)
+        err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer,
+                                                &size, NULL);
+      else
+        err = gnutls_x509_crq_get_key_purpose_oid (cert, indx, buffer,
                                                 &size, NULL);
+
       if (err < 0)
        {
          gnutls_free (buffer);
@@ -411,21 +421,21 @@ print_key_purpose (gnutls_string * str, gnutls_x509_crt_t cert)
        }
 
       if (strcmp (buffer, GNUTLS_KP_TLS_WWW_SERVER) == 0)
-       addf (str, _("\t\t\tTLS WWW Server.\n"));
+       addf (str, _("%s\t\t\tTLS WWW Server.\n"), prefix);
       else if (strcmp (buffer, GNUTLS_KP_TLS_WWW_CLIENT) == 0)
-       addf (str, _("\t\t\tTLS WWW Client.\n"));
+       addf (str, _("%s\t\t\tTLS WWW Client.\n"), prefix);
       else if (strcmp (buffer, GNUTLS_KP_CODE_SIGNING) == 0)
-       addf (str, _("\t\t\tCode signing.\n"));
+       addf (str, _("%s\t\t\tCode signing.\n"), prefix);
       else if (strcmp (buffer, GNUTLS_KP_EMAIL_PROTECTION) == 0)
-       addf (str, _("\t\t\tEmail protection.\n"));
+       addf (str, _("%s\t\t\tEmail protection.\n"), prefix);
       else if (strcmp (buffer, GNUTLS_KP_TIME_STAMPING) == 0)
-       addf (str, _("\t\t\tTime stamping.\n"));
+       addf (str, _("%s\t\t\tTime stamping.\n"), prefix);
       else if (strcmp (buffer, GNUTLS_KP_OCSP_SIGNING) == 0)
-       addf (str, _("\t\t\tOCSP signing.\n"));
+       addf (str, _("%s\t\t\tOCSP signing.\n"), prefix);
       else if (strcmp (buffer, GNUTLS_KP_ANY) == 0)
-       addf (str, _("\t\t\tAny purpose.\n"));
+       addf (str, _("%s\t\t\tAny purpose.\n"), prefix);
       else
-       addf (str, "\t\t\t%s\n", buffer);
+       addf (str, "%s\t\t\t%s\n", prefix, buffer);
 
       gnutls_free (buffer);
     }
@@ -718,7 +728,7 @@ int i, err;
                    critical ? _("critical") : _("not critical"));
 
 #ifdef ENABLE_PKI
-             if (type == TYPE_CRT) print_key_purpose (str, cert);
+             print_key_purpose (str, prefix, type, cert);
 #endif
 
              keypurpose_idx++;
index ba7a87dd299e88318e9311522278849c859397cf..7ff0fec8002c388462b5ce6ef4b69b6e8e3729db 100644 (file)
@@ -1900,6 +1900,43 @@ generate_request (void)
          ret = get_crl_sign_status ();
          if (ret)
            usage |= GNUTLS_KEY_CRL_SIGN;
+
+         ret = get_code_sign_status ();
+         if (ret)
+           {
+             ret =
+               gnutls_x509_crq_set_key_purpose_oid (crq,
+                                                    GNUTLS_KP_CODE_SIGNING,
+                                                    0);
+             if (ret < 0)
+               error (EXIT_FAILURE, 0, "key_kp: %s",
+                      gnutls_strerror (ret));
+           }
+
+         ret = get_ocsp_sign_status ();
+         if (ret)
+           {
+             ret =
+               gnutls_x509_crq_set_key_purpose_oid (crq,
+                                                    GNUTLS_KP_OCSP_SIGNING,
+                                                    0);
+             if (ret < 0)
+               error (EXIT_FAILURE, 0, "key_kp: %s",
+                      gnutls_strerror (ret));
+           }
+
+         ret = get_time_stamp_status ();
+         if (ret)
+           {
+             ret =
+               gnutls_x509_crq_set_key_purpose_oid (crq,
+                                                    GNUTLS_KP_TIME_STAMPING,
+                                                    0);
+             if (ret < 0)
+               error (EXIT_FAILURE, 0, "key_kp: %s",
+                      gnutls_strerror (ret));
+           }
+
     }
 
   ret = gnutls_x509_crq_set_key_usage (crq, usage);
@@ -1907,6 +1944,24 @@ generate_request (void)
     error (EXIT_FAILURE, 0, "key_usage: %s",
                   gnutls_strerror (ret));
 
+  ret = get_tls_client_status ();
+  if (ret != 0)
+    {
+       ret = gnutls_x509_crq_set_key_purpose_oid (crq,
+                               GNUTLS_KP_TLS_WWW_CLIENT, 0);
+       if (ret < 0) 
+         error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
+    }
+
+  ret = get_tls_server_status ();
+  if (ret != 0)
+    {
+      ret = gnutls_x509_crq_set_key_purpose_oid (crq,
+                                                GNUTLS_KP_TLS_WWW_SERVER, 0);
+      if (ret < 0)
+        error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
+    }
+
   ret = gnutls_x509_crq_set_key (crq, key);
   if (ret < 0)
     error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (ret));
@@ -1915,12 +1970,7 @@ generate_request (void)
   if (ret < 0)
     error (EXIT_FAILURE, 0, "sign: %s", gnutls_strerror (ret));
 
-  size = sizeof (buffer);
-  ret = gnutls_x509_crq_export (crq, info.outcert_format, buffer, &size);
-  if (ret < 0)
-    error (EXIT_FAILURE, 0, "export: %s", gnutls_strerror (ret));
-
-  fwrite (buffer, 1, size, outfile);
+  print_crq_info (crq, outfile);
 
   gnutls_x509_crq_deinit (crq);
   gnutls_x509_privkey_deinit (key);