]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added functions to parse the TLSFeatures X.509 extension.
authorTim Kosse <tim.kosse@filezilla-project.org>
Mon, 30 May 2016 07:45:29 +0000 (09:45 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 30 May 2016 08:14:57 +0000 (10:14 +0200)
In addition provide function to enumerate the features it lists,
and output information with the output functions.
This adds:
  gnutls_x509_tlsfeatures_init
  gnutls_x509_tlsfeatures_deinit
  gnutls_x509_tlsfeatures_get
  gnutls_x509_ext_import_tlsfeatures
  gnutls_x509_crt_get_tlsfeatures

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
lib/includes/gnutls/x509-ext.h
lib/includes/gnutls/x509.h
lib/pkix.asn
lib/pkix_asn1_tab.c
lib/x509/output.c
lib/x509/x509.c
lib/x509/x509_ext.c
lib/x509/x509_int.h

index b9b3a6d43e59444fae099ff5a8d19d8080617372..7af07b9ffb40a4c13e9c29842aa8fc7229b8f4ca 100644 (file)
@@ -185,6 +185,9 @@ int gnutls_x509_ext_import_policies(const gnutls_datum_t * ext, gnutls_x509_poli
 int gnutls_x509_ext_export_policies(gnutls_x509_policies_t policies,
                                 gnutls_datum_t * ext);
 
+int gnutls_x509_ext_import_tlsfeatures(const gnutls_datum_t * ext,
+                                                                          gnutls_x509_tlsfeatures_t,
+                                                                          unsigned int flags);
 
 /* *INDENT-OFF* */
 #ifdef __cplusplus
index 4c3d5b25a9284132f839cd2e8e04eb9acb1918dc..6f69617b3dd1b8afefb9ce0f4571af355b051e0c 100644 (file)
@@ -103,6 +103,7 @@ extern "C" {
 #define GNUTLS_X509EXT_OID_EXTENDED_KEY_USAGE "2.5.29.37"
 #define GNUTLS_X509EXT_OID_AUTHORITY_INFO_ACCESS "1.3.6.1.5.5.7.1.1"
 #define GNUTLS_X509EXT_OID_PROXY_CRT_INFO "1.3.6.1.5.5.7.1.14"
+#define GNUTLS_X509EXT_OID_TLSFEATURES "1.3.6.1.5.5.7.1.24"
 
 /* Certificate handling functions.
  */
@@ -454,6 +455,16 @@ int gnutls_x509_crt_get_proxy(gnutls_x509_crt_t cert,
                              char **policyLanguage,
                              char **policy, size_t * sizeof_policy);
 
+
+typedef struct gnutls_x509_tlsfeatures_st *gnutls_x509_tlsfeatures_t;
+
+int gnutls_x509_tlsfeatures_init(gnutls_x509_tlsfeatures_t *features);
+void gnutls_x509_tlsfeatures_deinit(gnutls_x509_tlsfeatures_t);
+int gnutls_x509_tlsfeatures_get(gnutls_x509_tlsfeatures_t f, unsigned idx, unsigned int *feature);
+
+int gnutls_x509_crt_get_tlsfeatures(gnutls_x509_crt_t cert,
+                                                                  gnutls_x509_tlsfeatures_t * features);
+
 #define GNUTLS_MAX_QUALIFIERS 8
 
   /**
index a5b53cd7b235b972d3cf2dfc8b70919968c2cab1..99cd54cba203157033af5709e7ecc83d8f457551 100644 (file)
@@ -687,4 +687,7 @@ GeneralSubtree ::= SEQUENCE {
      minimum         [0]     INTEGER DEFAULT 0,
      maximum         [1]     INTEGER OPTIONAL }
 
+-- rfc7633
+TlsFeatures ::= SEQUENCE OF INTEGER
+
 END
index 7c5ba126303683f5bdbf43790694e7ce86b921d6..4d78563ccd5bb2dab9a66d4a9a5c8a888e257866 100644 (file)
@@ -529,12 +529,14 @@ const asn1_static_node pkix_asn1_tab[] = {
   { "GeneralSubtrees", 1612709899, NULL },
   { "MAX", 1074266122, "1"},
   { NULL, 2, "GeneralSubtree"},
-  { "GeneralSubtree", 536870917, NULL },
+  { "GeneralSubtree", 1610612741, NULL },
   { "base", 1073741826, "GeneralName"},
   { "minimum", 1610653699, NULL },
   { NULL, 1073741833, "0"},
   { NULL, 4104, "0"},
   { "maximum", 536895491, NULL },
   { NULL, 4104, "1"},
+  { "TlsFeatures", 536870923, NULL },
+  { NULL, 3, NULL },
   { NULL, 0, NULL }
 };
index 34f2c70b6818f752d226ee598eca7f0a20eb8408..e63ca2d6d3c5eb2f50c1ac6c158aec04b22c6816 100644 (file)
@@ -880,6 +880,41 @@ print_unique_ids(gnutls_buffer_st * str, const gnutls_x509_crt_t cert)
        }
 }
 
+static void print_tlsfeatures(gnutls_buffer_st * str, const char *prefix, const gnutls_datum_t *der)
+{
+       int err;
+       int seq;
+       gnutls_x509_tlsfeatures_t features;
+       unsigned int feature;
+
+       err = gnutls_x509_tlsfeatures_init(&features);
+       if (err < 0)
+               return;
+
+       err = gnutls_x509_ext_import_tlsfeatures(der, features, 0);
+       if (err < 0) {
+               addf(str, "error: get_tlsfeatures: %s\n",
+                        gnutls_strerror(err));
+               goto cleanup;
+       }
+
+       for (seq=0;;seq++) {
+               err = gnutls_x509_tlsfeatures_get(features, seq, &feature);
+               if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+                       goto cleanup;
+               if (err < 0) {
+                       addf(str, "error: get_tlsfeatures: %s\n",
+                                gnutls_strerror(err));
+                       goto cleanup;
+               }
+
+               addf(str, "%s\t\t\t%u\n", prefix, feature);
+       }
+
+cleanup:
+       gnutls_x509_tlsfeatures_deinit(features);
+}
+
 struct ext_indexes_st {
        int san;
        int ian;
@@ -890,6 +925,7 @@ struct ext_indexes_st {
        int ski;
        int aki, nc;
        int crldist, pkey_usage_period;
+       int tlsfeatures;
 };
 
 static void print_extension(gnutls_buffer_st * str, const char *prefix,
@@ -1110,6 +1146,19 @@ static void print_extension(gnutls_buffer_st * str, const char *prefix,
                     critical ? _("critical") : _("not critical"));
 
                print_nc(str, prefix, der);
+       } else if (strcmp(oid, GNUTLS_X509EXT_OID_TLSFEATURES) == 0) {
+               if (idx->tlsfeatures) {
+                       addf(str,
+                                "warning: more than one tlsfeatures extension\n");
+               }
+
+               addf(str, _("%s\t\tTLS Features (%s):\n"),
+                        prefix,
+                        critical ? _("critical") : _("not critical"));
+
+               print_tlsfeatures(str, prefix, der);
+
+               idx->tlsfeatures++;
        } else {
                addf(str, _("%s\t\tUnknown extension %s (%s):\n"),
                     prefix, oid,
index 183e8b8b9d8a1a05caa82d2bef46bff8e6ff5015..16cc6be45d1815f714056ab718490ddedadfc1b1 100644 (file)
@@ -2051,6 +2051,131 @@ gnutls_x509_crt_get_proxy(gnutls_x509_crt_t cert,
        return 0;
 }
 
+/**
+ * gnutls_x509_tlsfeatures_init:
+ * @f: The TLS features
+ *
+ * This function will initialize a X.509 TLS features extention structure
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
+ *   otherwise a negative error value.
+ *
+ * Since: TBD
+ **/
+int gnutls_x509_tlsfeatures_init(gnutls_x509_tlsfeatures_t *f)
+{
+       *f = gnutls_calloc(1, sizeof(struct gnutls_x509_tlsfeatures_st));
+       if (*f == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+       return 0;
+}
+
+/**
+ * gnutls_x509_tlsfeatures_deinit:
+ * @f: The TLS features
+ *
+ * This function will deinitialize a X.509 TLS features extention structure
+ *
+ * Since: TBD
+ **/
+void gnutls_x509_tlsfeatures_deinit(gnutls_x509_tlsfeatures_t f)
+{
+       gnutls_free(f->features);
+       gnutls_free(f);
+}
+
+/**
+ * gnutls_x509_tlsfeatures_get:
+ * @f: The TLS features
+ * @idx: The index of the feature to get
+ * @feature: If the function succeeds, the feature will be stored in this variable
+ *
+ * This function will get a feature from the X.509 TLS features
+ * extention structure.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
+ *   otherwise a negative error value.
+ *
+ * Since: TBD
+ **/
+int gnutls_x509_tlsfeatures_get(gnutls_x509_tlsfeatures_t f, unsigned idx, unsigned int *feature)
+{
+       if (f == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       if (idx >= f->size) {
+               return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+       }
+
+       *feature = f->features[idx].feature;
+       return 0;
+}
+
+/**
+ * gnutls_x509_crt_get_tlsfeatures:
+ * @crt: A X.509 certificate
+ * @features: If the function succeeds, the
+ *   features will be stored in this variable.
+ *
+ * This function will get the X.509 TLS features
+ * extention structure from the certificate. The
+ * returned structure needs to be freed using
+ * gnutls_x509_tlsfeatures_deinit().
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
+ *   otherwise a negative error value.
+ *
+ * Since: TBD
+ **/
+int gnutls_x509_crt_get_tlsfeatures(gnutls_x509_crt_t crt,
+                                                                  gnutls_x509_tlsfeatures_t *features)
+{
+       int ret;
+       gnutls_datum_t der;
+       unsigned int critical;
+
+       if (crt == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       if ((ret =
+                _gnutls_x509_crt_get_extension(crt, GNUTLS_X509EXT_OID_TLSFEATURES, 0,
+                                               &der, &critical)) < 0)
+       {
+               return ret;
+       }
+
+       if (der.size == 0 || der.data == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+       }
+
+       ret = gnutls_x509_tlsfeatures_init(features);
+       if (ret < 0) {
+               gnutls_assert();
+               goto cleanup;
+       }
+
+       ret = gnutls_x509_ext_import_tlsfeatures(&der, *features, 0);
+       if (ret < 0) {
+               gnutls_assert();
+               goto cleanup;
+       }
+
+       gnutls_free(der.data);
+       return ret;
+
+ cleanup:
+       if (features != NULL)
+               gnutls_x509_tlsfeatures_deinit(*features);
+       gnutls_free(der.data);
+       return ret;
+}
+
 /**
  * gnutls_x509_policy_release:
  * @policy: a certificate policy
@@ -3845,7 +3970,7 @@ legacy_parse_aia(ASN1_TYPE src,
  *
  * If @what is %GNUTLS_IA_OCSP_URI, @data will hold the OCSP URI.
  * Requesting this @what value leads to an error if the accessMethod
- * is not 1.3.6.1.5.5.7.48.1 aka OSCP, or if accessLocation is not of
+ * is not 1.3.6.1.5.5.7.48.1 aka OCSP, or if accessLocation is not of
  * the "uniformResourceIdentifier" type. In that case %GNUTLS_E_UNKNOWN_ALGORITHM
  * will be returned, and @seq should be increased and this function
  * called again.
index 321124a140fe65d7779578528a0dca65330feede..0bf3b747d476141eb8d02d033f18a0ae3eedef74 100644 (file)
@@ -3151,3 +3151,100 @@ int _gnutls_x509_decode_ext(const gnutls_datum_t *der, gnutls_x509_ext_st *out)
        
 }
 
+
+static int parse_tlsfeatures(ASN1_TYPE c2, gnutls_x509_tlsfeatures_t f)
+{
+       char nptr[ASN1_MAX_NAME_SIZE];
+       int result;
+       void * tmp;
+       unsigned i, indx;
+       unsigned int feature;
+
+       for (i = 1;; i++) {
+               snprintf(nptr, sizeof(nptr), "?%u", i);
+
+               result = _gnutls_x509_read_uint(c2, nptr, &feature);
+
+               if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND || result == GNUTLS_E_ASN1_VALUE_NOT_FOUND) {
+                       break;
+               }
+               else if (result != GNUTLS_E_SUCCESS) {
+                       gnutls_assert();
+                       return _gnutls_asn2err(result);
+               }
+
+               if (feature > UINT16_MAX) {
+                       gnutls_assert();
+                       return GNUTLS_E_INTERNAL_ERROR;
+               }
+
+               indx = f->size;
+               tmp = gnutls_realloc(f->features, (f->size + 1) * sizeof(f->features[0]));
+               if (tmp == NULL) {
+                       return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+               }
+               f->features = tmp;
+
+               f->features[indx].feature = feature;
+
+               f->size++;
+       }
+
+       if (result < 0 && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+               return result;
+       }
+
+       return 0;
+}
+
+/**
+ * gnutls_x509_ext_import_tlsfeatures:
+ * @ext: The DER-encoded extension data
+ * @f: The features structure
+ * @flags: should be zero
+ *
+ * This function will export the features in the provided DER-encoded
+ * TLS Features PKIX extension, to a %gnutls_x509_tlsfeatures_t type. @f
+ * must be initialized.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
+ *
+ * Since: TBD
+ **/
+int gnutls_x509_ext_import_tlsfeatures(const gnutls_datum_t * ext,
+                                                                          gnutls_x509_tlsfeatures_t f,
+                                                                          unsigned int flags)
+{
+       int ret;
+       ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+
+       if (ext->size == 0 || ext->data == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+       }
+
+       ret = asn1_create_element(_gnutls_get_pkix(),
+                                 "PKIX1.TlsFeatures", &c2);
+       if (ret != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(ret);
+       }
+
+       ret = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
+       if (ret != ASN1_SUCCESS) {
+               gnutls_assert();
+               ret = _gnutls_asn2err(ret);
+               goto cleanup;
+       }
+
+       ret = parse_tlsfeatures(c2, f);
+       if (ret < 0) {
+               gnutls_assert();
+       }
+
+ cleanup:
+       asn1_delete_structure(&c2);
+
+       return ret;
+}
+
index 2c275f4b456801bc9cf6be034ea132687423c4be..b6f3e5fd96afe7a8ae8a8fc49a3fd31efd8ba721 100644 (file)
@@ -484,4 +484,11 @@ int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc,
 
 void _gnutls_x509_policies_erase(gnutls_x509_policies_t policies, unsigned int seq);
 
+struct gnutls_x509_tlsfeatures_st {
+       struct {
+               uint16_t feature;
+       } *features;
+       unsigned int size;
+};
+
 #endif