gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_3_1_4-26-g247ff3e


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_3_1_4-26-g247ff3e
Date: Sun, 18 Nov 2012 18:59:20 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=247ff3eecff914e2cc6b9377565232f8eb884af3

The branch, master has been updated
       via  247ff3eecff914e2cc6b9377565232f8eb884af3 (commit)
       via  c7f74089a5589d0b6f37bdc606b5db7699646bc2 (commit)
       via  d5bc73b10f216e086e3c31f3c6cca5057b524dfe (commit)
       via  9ba05ebdce5dc21af78399f5db21ccafad9c6e5f (commit)
       via  9e02a17f503668551356bdd10489b93c447834e4 (commit)
      from  96c38a6c89fe0b6f7d826c3588479ec861811054 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 247ff3eecff914e2cc6b9377565232f8eb884af3
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Nov 18 19:53:16 2012 +0100

    documented updates

commit c7f74089a5589d0b6f37bdc606b5db7699646bc2
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Nov 18 19:53:08 2012 +0100

    check for iconv

commit d5bc73b10f216e086e3c31f3c6cca5057b524dfe
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Nov 18 19:52:27 2012 +0100

    map the whole ascii set

commit 9ba05ebdce5dc21af78399f5db21ccafad9c6e5f
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Nov 18 19:38:38 2012 +0100

    Handle BMPString in DNs.

commit 9e02a17f503668551356bdd10489b93c447834e4
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Nov 18 19:31:54 2012 +0100

    Added functions to parse the certificate policies extention.
    
    Added gnutls_x509_crt_get_policy() etc. In addition several updated in the
    handling of strings in X.509 structures.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                       |   17 ++-
 configure.ac               |    2 +-
 lib/includes/gnutls/x509.h |   28 ++++
 lib/libgnutls.map          |    2 +
 lib/pkix.asn               |   28 ++++
 lib/pkix_asn1_tab.c        |   29 ++++-
 lib/system.c               |   78 ++++++++++++
 lib/system.h               |    1 +
 lib/tpm.c                  |   12 +-
 lib/x509/common.c          |  217 ++++++++++++++++++++++-----------
 lib/x509/common.h          |   26 +++-
 lib/x509/crl.c             |    2 +-
 lib/x509/dn.c              |    6 +-
 lib/x509/extensions.c      |    6 +-
 lib/x509/mpi.c             |    4 +-
 lib/x509/ocsp.c            |   90 ++++---------
 lib/x509/output.c          |   44 ++++++-
 lib/x509/pkcs12.c          |   37 +++---
 lib/x509/pkcs12_bag.c      |    6 +-
 lib/x509/privkey.c         |    2 +-
 lib/x509/privkey_pkcs8.c   |    8 +-
 lib/x509/x509.c            |  294 +++++++++++++++++++++++++++++++++++++++++---
 22 files changed, 729 insertions(+), 210 deletions(-)

diff --git a/NEWS b/NEWS
index 5dcec4d..b7e3d91 100644
--- a/NEWS
+++ b/NEWS
@@ -4,21 +4,26 @@ See the end for copying conditions.
 
 * Version 3.1.5 (unreleased)
 
+** libgnutls: Added functions to parse the certificates policies
+extension.
+
+** libgnutls: Added PKCS #11 key generation function that returns the 
+public key on generation.
+
+** libgnutls: Corrected bug in priority string parsing, that mostly 
+affected combined levels. Patch by Tim Kosse.
+
 ** certtool: The --pubkey-info option can be combined with the
 --load-privkey in order to print the corresponding public key of a private 
 key.
 
-** Added PKCS #11 key generation function that returns the public key
-on generation.
-
-** Corrected bug in priority string parsing, that mostly affected combined
-levels. Patch by Tim Kosse.
-
 ** p11tool: After key generation, outputs the public key (useful in
 tokens that do not store the public key).
 
 ** API and ABI modifications:
 gnutls_pkcs11_privkey_generate2: Added
+gnutls_x509_crt_get_policy: Added
+gnutls_certificate_policy_release: Added
 
 
 * Version 3.1.4 (released 2012-11-10)
diff --git a/configure.ac b/configure.ac
index 0891360..8ee03b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -199,7 +199,7 @@ AC_PROG_LIBTOOL
 
 
 dnl No fork on MinGW, disable some self-tests until we fix them.
-AC_CHECK_FUNCS([fork getrusage getpwuid_r daemon],,)
+AC_CHECK_FUNCS([fork getrusage getpwuid_r daemon iconv],,)
 AM_CONDITIONAL(HAVE_FORK, test "$ac_cv_func_fork" != "no")
 AC_LIB_HAVE_LINKFLAGS(pthread,, [#include <pthread.h>], [pthread_mutex_lock 
(0);])
 
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index a3cf725..88f5293 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -335,6 +335,34 @@ extern "C"
                                  char **policyLanguage,
                                  char **policy, size_t * sizeof_policy);
 
+#define GNUTLS_MAX_QUALIFIERS 16
+
+  /**
+   * gnutls_x509_qualifier_t:
+   * @GNUTLS_X509_QUALIFIER_UNKNOWN: Unknown qualifier.
+   * @GNUTLS_X509_QUALIFIER_URI: A URL
+   * @GNUTLS_X509_QUALIFIER_NOICE: A text notice.
+   *
+   * Enumeration of types for the X.509 qualifiers, of the certificate policy 
extension. 
+   */
+  typedef enum gnutls_x509_qualifier_t 
+  {
+    GNUTLS_X509_QUALIFIER_UNKNOWN = 0, GNUTLS_X509_QUALIFIER_URI, 
+    GNUTLS_X509_QUALIFIER_NOTICE
+  } gnutls_x509_qualifier_t;
+
+  struct gnutls_certificate_policy_st 
+    {
+      char* policy_oid;
+      unsigned int qualifiers;
+      gnutls_x509_qualifier_t qualifier_type[GNUTLS_MAX_QUALIFIERS];
+      char *qualifier_data[GNUTLS_MAX_QUALIFIERS];
+    };
+
+  void gnutls_certificate_policy_release(struct gnutls_certificate_policy_st* 
policy);
+  int gnutls_x509_crt_get_policy (gnutls_x509_crt_t crt, int indx, 
+                                  struct gnutls_certificate_policy_st* policy,
+                                  unsigned int * critical);
   int gnutls_x509_dn_oid_known (const char *oid);
 
 #define GNUTLS_X509_DN_OID_RETURN_OID 1
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index fb77313..f9b3a46 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -871,6 +871,8 @@ GNUTLS_3_1_0 {
        gnutls_ocsp_status_request_is_checked;
        gnutls_sign_is_secure;
        gnutls_pkcs11_privkey_generate2;
+       gnutls_x509_crt_get_policy;
+       gnutls_certificate_policy_release;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
diff --git a/lib/pkix.asn b/lib/pkix.asn
index 3f1682c..235b6d7 100644
--- a/lib/pkix.asn
+++ b/lib/pkix.asn
@@ -552,6 +552,34 @@ ProxyPolicy ::= SEQUENCE {
   policyLanguage   OBJECT IDENTIFIER,
   policy           OCTET STRING OPTIONAL }
 
+-- 2.5.29.32
+
+
+certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+
+PolicyInformation ::= SEQUENCE {
+  policyIdentifier   OBJECT IDENTIFIER,
+  policyQualifiers   SEQUENCE SIZE (1..MAX) OF PolicyQualifierInfo OPTIONAL }
+
+PolicyQualifierInfo ::= SEQUENCE {
+  policyQualifierId  OBJECT IDENTIFIER,
+  qualifier          ANY DEFINED BY policyQualifierId }
+
+CPSuri ::= IA5String
+
+UserNotice ::= SEQUENCE {
+  noticeRef        NoticeReference OPTIONAL,
+  explicitText     DisplayText OPTIONAL }
+
+NoticeReference ::= SEQUENCE {
+  organization     DisplayText,
+  noticeNumbers    SEQUENCE OF INTEGER }
+
+DisplayText ::= CHOICE {
+  ia5String        IA5String      (SIZE (1..200)),
+  bmpString        BMPString      (SIZE (1..200)),
+  utf8String       UTF8String     (SIZE (1..200)) }
+
 -- rfc2560
 
 OCSPRequest     ::=     SEQUENCE {
diff --git a/lib/pkix_asn1_tab.c b/lib/pkix_asn1_tab.c
index ac5b0ab..280c7cc 100644
--- a/lib/pkix_asn1_tab.c
+++ b/lib/pkix_asn1_tab.c
@@ -4,7 +4,7 @@
 
 #include <libtasn1.h>
 
-const ASN1_ARRAY_TYPE pkix_asn1_tab[] = {
+const asn1_static_node pkix_asn1_tab[] = {
   { "PKIX1", 536875024, NULL },
   { NULL, 1073741836, NULL },
   { "id-pkix", 1879048204, NULL },
@@ -388,6 +388,33 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[] = {
   { "ProxyPolicy", 1610612741, NULL },
   { "policyLanguage", 1073741836, NULL },
   { "policy", 16391, NULL },
+  { "certificatePolicies", 1612709899, NULL },
+  { "MAX", 1074266122, "1"},
+  { NULL, 2, "PolicyInformation"},
+  { "PolicyInformation", 1610612741, NULL },
+  { "policyIdentifier", 1073741836, NULL },
+  { "policyQualifiers", 538984459, NULL },
+  { "MAX", 1074266122, "1"},
+  { NULL, 2, "PolicyQualifierInfo"},
+  { "PolicyQualifierInfo", 1610612741, NULL },
+  { "policyQualifierId", 1073741836, NULL },
+  { "qualifier", 541065229, NULL },
+  { "policyQualifierId", 1, NULL },
+  { "CPSuri", 1073741826, "IA5String"},
+  { "UserNotice", 1610612741, NULL },
+  { "noticeRef", 1073758210, "NoticeReference"},
+  { "explicitText", 16386, "DisplayText"},
+  { "NoticeReference", 1610612741, NULL },
+  { "organization", 1073741826, "DisplayText"},
+  { "noticeNumbers", 536870923, NULL },
+  { NULL, 3, NULL },
+  { "DisplayText", 1610612754, NULL },
+  { "ia5String", 1612709890, "IA5String"},
+  { "200", 524298, "1"},
+  { "bmpString", 1612709890, "BMPString"},
+  { "200", 524298, "1"},
+  { "utf8String", 538968066, "UTF8String"},
+  { "200", 524298, "1"},
   { "OCSPRequest", 1610612741, NULL },
   { "tbsRequest", 1073741826, "TBSRequest"},
   { "optionalSignature", 536895490, "Signature"},
diff --git a/lib/system.c b/lib/system.c
index 39a65a3..285ffbd 100644
--- a/lib/system.c
+++ b/lib/system.c
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <c-ctype.h>
 
 #ifdef _WIN32
 # include <windows.h>
@@ -471,3 +472,80 @@ 
gnutls_x509_trust_list_add_system_trust(gnutls_x509_trust_list_t list,
   return r;
 #endif
 }
+
+#if defined(HAVE_ICONV)
+
+# include <iconv.h>
+
+int _gnutls_ucs2_to_utf8(const void* data, size_t size, gnutls_datum_t *output)
+{
+iconv_t conv;
+int ret;
+size_t orig, dstlen = size*2;
+char* src = (void*)data;
+char* dst, *pdst;
+
+  if (size == 0)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+    
+  conv = iconv_open("UTF-8", "UTF-16BE");
+  if (conv == (iconv_t)-1)
+    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+  
+  pdst = dst = gnutls_malloc(dstlen+1);
+  if (dst == NULL)
+    {
+      ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+      goto cleanup;
+    }
+
+  orig = dstlen;
+  ret = iconv(conv, &src, &size, &pdst, &dstlen);
+  if (ret == -1)
+    {
+      ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+      goto cleanup;
+    }
+    
+
+  output->data = (void*)dst;
+  output->size = orig-dstlen;
+  output->data[output->size] = 0;
+
+  ret = 0;
+  
+cleanup:
+  iconv_close(conv);
+  
+  return ret;
+}
+#else
+
+/* Can convert only english */
+int _gnutls_ucs2_to_utf8(const void* data, size_t size, gnutls_datum_t *output)
+{
+unsigned int i, j;
+char* dst;
+const char *src = data;
+
+  if (size == 0 || size % 2 != 0)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+  dst = gnutls_malloc(size+1);
+  if (dst == NULL)
+    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+  for (i=j=0;i<size;i+=2,j++)
+    {
+      if (src[i] != 0 || !isascii(src[i+1]))
+        return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+      dst[j] = src[i+1];
+    }
+    
+  output->data = (void*)dst;
+  output->size = j;
+  output->data[output->size] = 0;
+
+  return 0;
+}
+#endif
diff --git a/lib/system.h b/lib/system.h
index 2902695..39b9548 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -70,6 +70,7 @@ struct timespec ts;
 }
 
 int _gnutls_find_config_path(char* path, size_t max_size);
+int _gnutls_ucs2_to_utf8(const void* data, size_t size, gnutls_datum_t 
*output);
 
 int gnutls_system_global_init (void);
 void gnutls_system_global_deinit (void);
diff --git a/lib/tpm.c b/lib/tpm.c
index e9c8123..d1d74ce 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -367,10 +367,11 @@ static int load_key(TSS_HCONTEXT tpm_ctx, TSS_HKEY srk,
 {
 int ret, err;
 gnutls_datum_t asn1 = { NULL, 0 };
-size_t slen;
 
   if (format == GNUTLS_TPMKEY_FMT_CTK_PEM)
     {
+      gnutls_datum_t td;
+
       ret = gnutls_pem_base64_decode_alloc ("TSS KEY BLOB", fdata, &asn1);
       if (ret)
         {
@@ -380,14 +381,15 @@ size_t slen;
           return ret;
         }
 
-      slen = asn1.size;
-      ret = _gnutls_x509_decode_octet_string(NULL, asn1.data, asn1.size, 
asn1.data, &slen);
+      ret = _gnutls_x509_decode_string(NULL, asn1.data, asn1.size, &td);
       if (ret < 0)
         {
           gnutls_assert();
           goto cleanup;
         }
-      asn1.size = slen;
+      gnutls_free(asn1.data);
+      asn1.data = td.data;
+      asn1.size = td.size;
     }
   else /* DER */
     {
@@ -1359,7 +1361,7 @@ uint8_t buf[32];
       
       if (format == GNUTLS_TPMKEY_FMT_CTK_PEM)
         {
-          ret = _gnutls_x509_encode_octet_string(tdata, tint, &tmpkey);
+          ret = _gnutls_x509_encode_string(NULL, tdata, tint, &tmpkey);
           if (ret < 0)
             {
               gnutls_assert();
diff --git a/lib/x509/common.c b/lib/x509/common.c
index d577f8a..fa4dbdc 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -230,8 +230,8 @@ _gnutls_x509_oid_data2string (const char *oid, void *value,
                               int value_size, char *res, size_t * res_size)
 {
   char str[MAX_STRING_LEN], tmpname[128];
-  const char *ANAME = NULL;
-  int CHOICE = -1, len = -1, result;
+  const char *aname = NULL;
+  int choice = -1, len = -1, result;
   ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY;
   char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";
 
@@ -247,17 +247,17 @@ _gnutls_x509_oid_data2string (const char *oid, void 
*value,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
-  ANAME = _gnutls_x509_oid2asn_string (oid);
-  CHOICE = _gnutls_x509_oid_data_choice (oid);
+  aname = _gnutls_x509_oid2asn_string (oid);
+  choice = _gnutls_x509_oid_data_choice (oid);
 
-  if (ANAME == NULL)
+  if (aname == NULL)
     {
       gnutls_assert ();
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
   if ((result =
-       asn1_create_element (_gnutls_get_pkix (), ANAME,
+       asn1_create_element (_gnutls_get_pkix (), aname,
                             &tmpasn)) != ASN1_SUCCESS)
     {
       gnutls_assert ();
@@ -285,7 +285,7 @@ _gnutls_x509_oid_data2string (const char *oid, void *value,
       return _gnutls_asn2err (result);
     }
 
-  if (CHOICE == 0)
+  if (choice == 0)
     {
       str[len] = 0;
 
@@ -300,14 +300,15 @@ _gnutls_x509_oid_data2string (const char *oid, void 
*value,
       asn1_delete_structure (&tmpasn);
     }
   else
-    {                           /* CHOICE */
+    {                           /* choice */
       int non_printable = 0, teletex = 0;
+      int ucs2 = 0;
       str[len] = 0;
 
       /* Note that we do not support strings other than
        * UTF-8 (thus ASCII as well).
        */
-      if (strcmp (str, "printableString") != 0 &&
+      if (strcmp (str, "printableString") != 0 && strcmp (str, "bmpString") != 
0 && 
           strcmp (str, "ia5String") != 0 && strcmp (str, "utf8String") != 0)
         {
           non_printable = 1;
@@ -315,6 +316,8 @@ _gnutls_x509_oid_data2string (const char *oid, void *value,
       if (strcmp (str, "teletexString") == 0)
         teletex = 1;
 
+      if (strcmp (str, "bmpString") == 0)
+        ucs2 = 1;
 
       _gnutls_str_cpy (tmpname, sizeof (tmpname), str);
 
@@ -327,8 +330,27 @@ _gnutls_x509_oid_data2string (const char *oid, void *value,
         }
 
       asn1_delete_structure (&tmpasn);
+      
+      if (ucs2 != 0)
+        {
+          gnutls_datum_t td;
 
-      if (teletex != 0)
+          result = _gnutls_ucs2_to_utf8(str, len, &td);
+          if (result < 0)
+            return gnutls_assert_val(result);
+            
+          if (td.size >= sizeof(str))
+            {
+              gnutls_free(td.data);
+              return gnutls_assert_val(GNUTLS_E_ASN1_DER_ERROR);
+            }
+            
+          memcpy(str, td.data, td.size);
+          len = td.size;
+          
+          gnutls_free(td.data);
+        }
+      else if (teletex != 0)
         {
           int ascii = 0, i;
           /* HACK: if the teletex string contains only ascii
@@ -664,7 +686,7 @@ _gnutls_x509_get_time (ASN1_TYPE c2, const char *when, int 
nochoice)
     {
       _gnutls_str_cpy (name, sizeof (name), when);
 
-      /* CHOICE */
+      /* choice */
       if (strcmp (ttime, "generalTime") == 0)
         {
           _gnutls_str_cat (name, sizeof (name), ".generalTime");
@@ -853,15 +875,15 @@ _gnutls_x509_export_int_named2 (ASN1_TYPE asn1_data, 
const char *name,
  * etc.
  */
 int
-_gnutls_x509_decode_octet_string (const char *string_type,
-                                  const uint8_t * der, size_t der_size,
-                                  uint8_t * output, size_t * output_size)
+_gnutls_x509_decode_string (const char *string_type,
+                            const uint8_t * der, size_t der_size,
+                            gnutls_datum_t * output)
 {
   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
-  int result, tmp_output_size;
+  int result;
   char strname[64];
 
-  if (string_type == NULL)
+  if (string_type == NULL) /* assume octet string */
     _gnutls_str_cpy (strname, sizeof (strname), "PKIX1.pkcs-7-Data");
   else
     {
@@ -885,16 +907,15 @@ _gnutls_x509_decode_octet_string (const char *string_type,
       goto cleanup;
     }
 
-  tmp_output_size = *output_size;
-  result = asn1_read_value (c2, "", output, &tmp_output_size);
-  *output_size = (size_t)tmp_output_size;
-
-  if (result != ASN1_SUCCESS)
+  result = _gnutls_x509_read_value(c2, "", output);
+  if (result < 0)
     {
       gnutls_assert ();
-      result = _gnutls_asn2err (result);
       goto cleanup;
     }
+  
+  /* This is allowed since _gnutls_x509_read_value allocates one more */
+  output->data[output->size] = 0;
 
   result = 0;
 
@@ -908,13 +929,60 @@ cleanup:
 
 /* Reads a value from an ASN1 tree, and puts the output
  * in an allocated variable in the given datum.
- * flags == 0 do nothing  with the DER output
- * flags == 1 parse the DER output as OCTET STRING
- * flags == 2 the value is a BIT STRING
+ *
+ * Note that this function always places allocates one plus
+ * the required data size (to allow for a null byte).
  */
 int
 _gnutls_x509_read_value (ASN1_TYPE c, const char *root,
-                         gnutls_datum_t * ret, int flags)
+                         gnutls_datum_t * ret)
+{
+  int len = 0, result;
+  uint8_t *tmp = NULL;
+
+  result = asn1_read_value (c, root, NULL, &len);
+  if (result != ASN1_MEM_ERROR)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      return result;
+    }
+
+  tmp = gnutls_malloc ((size_t)len+1);
+  if (tmp == NULL)
+    {
+      gnutls_assert ();
+      result = GNUTLS_E_MEMORY_ERROR;
+      goto cleanup;
+    }
+
+  result = asn1_read_value (c, root, tmp, &len);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  ret->data = tmp;
+  ret->size = (unsigned)len;
+
+  return 0;
+
+cleanup:
+  gnutls_free (tmp);
+  return result;
+}
+
+/* Reads a value from an ASN1 tree, and puts the output
+ * in an allocated variable in the given datum.
+ *
+ * Note that this function always places a null character
+ * at the end of a readable string value (which is not accounted into size)
+ */
+int
+_gnutls_x509_read_string (ASN1_TYPE c, const char *root,
+                          gnutls_datum_t * ret, x509_string_type type)
 {
   int len = 0, result;
   size_t slen;
@@ -928,10 +996,10 @@ _gnutls_x509_read_value (ASN1_TYPE c, const char *root,
       return result;
     }
 
-  if (flags == 2)
+  if (type == RV_BIT_STRING)
     len /= 8;
 
-  tmp = gnutls_malloc ((size_t)len);
+  tmp = gnutls_malloc ((size_t)len+1);
   if (tmp == NULL)
     {
       gnutls_assert ();
@@ -947,43 +1015,62 @@ _gnutls_x509_read_value (ASN1_TYPE c, const char *root,
       goto cleanup;
     }
 
-  if (flags == 2)
+  if (type == RV_BIT_STRING)
     len /= 8;
 
-  /* Extract the OCTET STRING.
+  /* Extract the STRING.
    */
-
-  if (flags == 1)
+  if (type == RV_IA5STRING || type == RV_UTF8STRING || type == RV_OCTET_STRING)
     {
+      const char* sname;
       slen = (size_t)len;
-      result = _gnutls_x509_decode_octet_string (NULL, tmp, slen, tmp, &slen);
+
+      if (type == RV_UTF8STRING)
+        sname = "UTF8String";
+      else if (type == RV_IA5STRING)
+        sname = "IA5String";
+      else
+        sname = NULL;
+
+      result = _gnutls_x509_decode_string (sname, tmp, slen, ret);
       if (result < 0)
         {
           gnutls_assert ();
           goto cleanup;
         }
-      len = slen;
+      gnutls_free(tmp);
+    }
+  else
+    {
+      ret->data = tmp;
+      ret->size = (unsigned)len;
     }
-
-  ret->data = tmp;
-  ret->size = (unsigned)len;
 
   return 0;
 
 cleanup:
   gnutls_free (tmp);
   return result;
-
 }
 
-int _gnutls_x509_encode_octet_string(const void* input_data, size_t input_size,
-                                     gnutls_datum_t* output)
+/* The string type should be IA5String, UTF8String etc. Leave
+ * null for octet string */
+int _gnutls_x509_encode_string(const char* string_type, 
+                               const void* input_data, size_t input_size,
+                               gnutls_datum_t* output)
 {
   int ret;
   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
-
+  char strname[64];
+  
+  _gnutls_str_cpy (strname, sizeof (strname), "PKIX1.");
+  if (string_type == NULL)
+    _gnutls_str_cat (strname, sizeof (strname), "pkcs-7-Data");
+  else
+    _gnutls_str_cat (strname, sizeof (strname), string_type);
+  
   if ((ret = asn1_create_element
-       (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS)
+       (_gnutls_get_pkix (), strname, &c2)) != ASN1_SUCCESS)
     {
       gnutls_assert ();
       ret = _gnutls_asn2err (ret);
@@ -1140,39 +1227,27 @@ _gnutls_x509_der_encode_and_copy (ASN1_TYPE src, const 
char *src_name,
  */
 int
 _gnutls_x509_write_value (ASN1_TYPE c, const char *root,
-                          const gnutls_datum_t * data, int str)
+                          const gnutls_datum_t * data, x509_string_type type)
 {
-  int result;
+  int ret;
   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
   gnutls_datum_t val = { NULL, 0 };
+  const char* sname = NULL;
 
-  if (str)
+  if (type == RV_OCTET_STRING || type == RV_IA5STRING || type == RV_UTF8STRING)
     {
-      /* Convert it to OCTET STRING
-       */
-      if ((result = asn1_create_element
-           (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS)
-        {
-          gnutls_assert ();
-          result = _gnutls_asn2err (result);
-          goto cleanup;
-        }
-
-      result = asn1_write_value (c2, "", data->data, data->size);
-      if (result != ASN1_SUCCESS)
-        {
-          gnutls_assert ();
-          result = _gnutls_asn2err (result);
-          goto cleanup;
-        }
+    
+      if (type == RV_IA5STRING)
+        sname = "IA5String";
+      else if (type == RV_UTF8STRING)
+        sname = "UTF8String";
 
-      result = _gnutls_x509_der_encode (c2, "", &val, 0);
-      if (result < 0)
+      ret = _gnutls_x509_encode_string(sname, data->data, data->size, &val);
+      if (ret < 0)
         {
           gnutls_assert ();
           goto cleanup;
         }
-
     }
   else
     {
@@ -1182,21 +1257,21 @@ _gnutls_x509_write_value (ASN1_TYPE c, const char *root,
 
   /* Write the data.
    */
-  result = asn1_write_value (c, root, val.data, val.size);
-  if (result != ASN1_SUCCESS)
+  ret = asn1_write_value (c, root, val.data, val.size);
+  if (ret != ASN1_SUCCESS)
     {
       gnutls_assert ();
-      result = _gnutls_asn2err (result);
+      ret = _gnutls_asn2err (ret);
       goto cleanup;
     }
 
-  result = 0;
+  ret = 0;
 
 cleanup:
   asn1_delete_structure (&c2);
   if (val.data != data->data)
     _gnutls_free_datum (&val);
-  return result;
+  return ret;
 }
 
 void
@@ -1443,7 +1518,7 @@ _gnutls_x509_get_signature_algorithm (ASN1_TYPE src, 
const char *src_name)
    * read. They will be read from the issuer's certificate if needed.
    */
   result =
-    _gnutls_x509_read_value (src, src_name, &sa, 0);
+    _gnutls_x509_read_value (src, src_name, &sa);
 
   if (result < 0)
     {
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 1ee9194..4b38884 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -66,13 +66,23 @@
 #define ASN1_NULL "\x05\x00"
 #define ASN1_NULL_SIZE 2
 
+typedef enum x509_string_type {
+  RV_RAW,
+  RV_OCTET_STRING,
+  RV_BIT_STRING,
+  RV_IA5STRING,
+  RV_UTF8STRING
+} x509_string_type;
+
 int _gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim, int 
general);
 
-int _gnutls_x509_decode_octet_string (const char *string_type,
-                                      const uint8_t * der, size_t der_size,
-                                      uint8_t * output, size_t * output_size);
-int _gnutls_x509_encode_octet_string(const void* input_data, size_t input_size,
-                                     gnutls_datum_t* output);
+int _gnutls_x509_decode_string (const char *string_type,
+                                const uint8_t * der, size_t der_size,
+                                gnutls_datum_t *output);
+
+int _gnutls_x509_encode_string(const char* string_type,
+                               const void* input_data, size_t input_size,
+                               gnutls_datum_t* output);
 
 int _gnutls_x509_oid_data2string (const char *OID, void *value,
                                   int value_size, char *res,
@@ -112,9 +122,11 @@ int _gnutls_x509_export_int_named2 (ASN1_TYPE asn1_data, 
const char *name,
                                     gnutls_datum_t * out);
 
 int _gnutls_x509_read_value (ASN1_TYPE c, const char *root,
-                             gnutls_datum_t * ret, int str);
+                             gnutls_datum_t * ret);
+int _gnutls_x509_read_string (ASN1_TYPE c, const char *root,
+                             gnutls_datum_t * ret, x509_string_type type);
 int _gnutls_x509_write_value (ASN1_TYPE c, const char *root,
-                              const gnutls_datum_t * data, int str);
+                              const gnutls_datum_t * data, x509_string_type 
type);
 
 int _gnutls_x509_encode_and_write_attribute (const char *given_oid,
                                              ASN1_TYPE asn1_struct,
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index 8acc64c..f156b43 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -286,7 +286,7 @@ gnutls_x509_crl_get_signature_algorithm (gnutls_x509_crl_t 
crl)
 
   result =
     _gnutls_x509_read_value (crl->crl, "signatureAlgorithm.algorithm",
-                             &sa, 0);
+                             &sa);
 
   if (result < 0)
     {
diff --git a/lib/x509/dn.c b/lib/x509/dn.c
index 9c60961..9506969 100644
--- a/lib/x509/dn.c
+++ b/lib/x509/dn.c
@@ -834,8 +834,10 @@ _gnutls_x509_decode_and_read_attribute (ASN1_TYPE 
asn1_struct,
   if (multi)
     _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), "s.?1");    /* .values.?1 
*/
 
-  result =
-    _gnutls_x509_read_value (asn1_struct, tmpbuffer, value, octet_string);
+  if (octet_string)
+    result = _gnutls_x509_read_string (asn1_struct, tmpbuffer, value, 
RV_OCTET_STRING);
+  else
+    result = _gnutls_x509_read_value (asn1_struct, tmpbuffer, value);
   if (result < 0)
     {
       gnutls_assert ();
diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c
index a429bfe..c251b0d 100644
--- a/lib/x509/extensions.c
+++ b/lib/x509/extensions.c
@@ -122,7 +122,7 @@ get_extension (ASN1_TYPE asn, const char *root,
               _gnutls_str_cpy (name2, sizeof (name2), name);
               _gnutls_str_cat (name2, sizeof (name2), ".extnValue");
 
-              result = _gnutls_x509_read_value (asn, name2, &value, 0);
+              result = _gnutls_x509_read_value (asn, name2, &value);
               if (result < 0)
                 {
                   gnutls_assert ();
@@ -1254,7 +1254,7 @@ _gnutls_x509_ext_extract_proxyCertInfo (int 
*pathLenConstraint,
     }
 
   result = _gnutls_x509_read_value (ext, "proxyPolicy.policyLanguage",
-                                    &value, 0);
+                                    &value);
   if (result < 0)
     {
       gnutls_assert ();
@@ -1265,7 +1265,7 @@ _gnutls_x509_ext_extract_proxyCertInfo (int 
*pathLenConstraint,
   if (policyLanguage)
     *policyLanguage = gnutls_strdup ((char*)value.data);
 
-  result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value, 0);
+  result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value);
   if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
     {
       if (policy)
diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c
index c9d3058..7792c58 100644
--- a/lib/x509/mpi.c
+++ b/lib/x509/mpi.c
@@ -97,7 +97,7 @@ _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
   /* Read the algorithm's parameters
    */
   _asnstr_append_name (name, sizeof (name), root, ".subjectPublicKey");
-  result = _gnutls_x509_read_value (asn, name, &tmp, 2);
+  result = _gnutls_x509_read_string (asn, name, &tmp, RV_BIT_STRING);
 
   if (result < 0)
     {
@@ -126,7 +126,7 @@ _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
 
   if (pk_algorithm != GNUTLS_PK_RSA) /* RSA doesn't use parameters */
     {
-      result = _gnutls_x509_read_value (asn, name, &tmp, 0);
+      result = _gnutls_x509_read_value (asn, name, &tmp);
       if (result < 0) 
         {
           gnutls_assert ();
diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c
index 8756431..87a2503 100644
--- a/lib/x509/ocsp.c
+++ b/lib/x509/ocsp.c
@@ -267,7 +267,7 @@ gnutls_ocsp_resp_import (gnutls_ocsp_resp_t resp,
     return GNUTLS_E_SUCCESS;
 
   ret = _gnutls_x509_read_value (resp->resp, "responseBytes.responseType",
-                                &resp->response_type_oid, 0);
+                                &resp->response_type_oid);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -296,7 +296,7 @@ gnutls_ocsp_resp_import (gnutls_ocsp_resp_t resp,
        }
 
       ret = _gnutls_x509_read_value (resp->resp, "responseBytes.response",
-                                    &d, 0);
+                                    &d);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -482,7 +482,7 @@ gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req,
   snprintf (name, sizeof (name),
            "tbsRequest.requestList.?%u.reqCert.hashAlgorithm.algorithm",
            indx + 1);
-  ret = _gnutls_x509_read_value (req->req, name, &sa, 0);
+  ret = _gnutls_x509_read_value (req->req, name, &sa);
   if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
     return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
   else if (ret < 0)
@@ -506,7 +506,7 @@ gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req,
     {
       snprintf (name, sizeof (name),
                "tbsRequest.requestList.?%u.reqCert.issuerNameHash", indx + 1);
-      ret = _gnutls_x509_read_value (req->req, name, issuer_name_hash, 0);
+      ret = _gnutls_x509_read_value (req->req, name, issuer_name_hash);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -518,7 +518,7 @@ gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req,
     {
       snprintf (name, sizeof (name),
                "tbsRequest.requestList.?%u.reqCert.issuerKeyHash", indx + 1);
-      ret = _gnutls_x509_read_value (req->req, name, issuer_key_hash, 0);
+      ret = _gnutls_x509_read_value (req->req, name, issuer_key_hash);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -532,7 +532,7 @@ gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req,
     {
       snprintf (name, sizeof (name),
                "tbsRequest.requestList.?%u.reqCert.serialNumber", indx + 1);
-      ret = _gnutls_x509_read_value (req->req, name, serial_number, 0);
+      ret = _gnutls_x509_read_value (req->req, name, serial_number);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -718,9 +718,9 @@ gnutls_ocsp_req_add_cert (gnutls_ocsp_req_t req,
   inh.size = inhlen;
   inh.data = inh_buf;
 
-  ret = _gnutls_x509_read_value
+  ret = _gnutls_x509_read_string
     (issuer->cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
-     &tmp, 2);
+     &tmp, RV_BIT_STRING);
   if (ret != GNUTLS_E_SUCCESS)
     {
       gnutls_assert ();
@@ -738,7 +738,7 @@ gnutls_ocsp_req_add_cert (gnutls_ocsp_req_t req,
   ikh.data = ikh_buf;
 
   ret = _gnutls_x509_read_value (cert->cert, "tbsCertificate.serialNumber",
-                                &sn, 0);
+                                &sn);
   if (ret != GNUTLS_E_SUCCESS)
     {
       gnutls_assert ();
@@ -821,7 +821,7 @@ gnutls_ocsp_req_get_extension (gnutls_ocsp_req_t req,
     {
       snprintf (name, sizeof (name),
                "tbsRequest.requestExtensions.?%u.extnID", indx + 1);
-      ret = _gnutls_x509_read_value (req->req, name, oid, 0);
+      ret = _gnutls_x509_read_value (req->req, name, oid);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -833,7 +833,7 @@ gnutls_ocsp_req_get_extension (gnutls_ocsp_req_t req,
     {
       snprintf (name, sizeof (name),
                "tbsRequest.requestExtensions.?%u.extnValue", indx + 1);
-      ret = _gnutls_x509_read_value (req->req, name, data, 0);
+      ret = _gnutls_x509_read_value (req->req, name, data);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -896,7 +896,6 @@ gnutls_ocsp_req_get_nonce (gnutls_ocsp_req_t req,
                           gnutls_datum_t *nonce)
 {
   int ret;
-  size_t l = 0;
   gnutls_datum_t tmp;
 
   if (req == NULL || nonce == NULL)
@@ -914,32 +913,16 @@ gnutls_ocsp_req_get_nonce (gnutls_ocsp_req_t req,
       return ret;
     }
 
-  ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
-                                         NULL, &l);
-  if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+  ret = _gnutls_x509_decode_string (NULL, tmp.data, (size_t) tmp.size,
+                                   nonce);
+  if (ret < 0)
     {
       gnutls_assert ();
       gnutls_free (tmp.data);
       return ret;
     }
 
-  nonce->data = gnutls_malloc (l);
-  if (nonce->data == NULL)
-    {
-      gnutls_assert ();
-      gnutls_free (tmp.data);
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
-                                         nonce->data, &l);
   gnutls_free (tmp.data);
-  if (ret != GNUTLS_E_SUCCESS)
-    {
-      gnutls_assert ();
-      return ret;
-    }
-  nonce->size = l;
 
   return GNUTLS_E_SUCCESS;
 }
@@ -1121,7 +1104,7 @@ gnutls_ocsp_resp_get_response (gnutls_ocsp_resp_t resp,
   if (response_type_oid != NULL)
     {
       ret = _gnutls_x509_read_value (resp->resp, "responseBytes.responseType",
-                                    response_type_oid, 0);
+                                    response_type_oid);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -1132,7 +1115,7 @@ gnutls_ocsp_resp_get_response (gnutls_ocsp_resp_t resp,
   if (response != NULL)
     {
       ret = _gnutls_x509_read_value (resp->resp, "responseBytes.response",
-                                    response, 0);
+                                    response);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -1418,7 +1401,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp,
   snprintf (name, sizeof (name),
            "tbsResponseData.responses.?%u.certID.hashAlgorithm.algorithm",
            indx + 1);
-  ret = _gnutls_x509_read_value (resp->basicresp, name, &sa, 0);
+  ret = _gnutls_x509_read_value (resp->basicresp, name, &sa);
   if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
     return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
   else if (ret < 0)
@@ -1444,7 +1427,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp,
                "tbsResponseData.responses.?%u.certID.issuerNameHash",
                indx + 1);
       ret = _gnutls_x509_read_value (resp->basicresp, name,
-                                    issuer_name_hash, 0);
+                                    issuer_name_hash);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -1458,7 +1441,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp,
                "tbsResponseData.responses.?%u.certID.issuerKeyHash",
                indx + 1);
       ret = _gnutls_x509_read_value (resp->basicresp, name,
-                                    issuer_key_hash, 0);
+                                    issuer_key_hash);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -1474,7 +1457,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp,
                "tbsResponseData.responses.?%u.certID.serialNumber",
                indx + 1);
       ret = _gnutls_x509_read_value (resp->basicresp, name,
-                                    serial_number, 0);
+                                    serial_number);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -1491,7 +1474,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp,
       snprintf (name, sizeof (name),
                "tbsResponseData.responses.?%u.certStatus",
                indx + 1);
-      ret = _gnutls_x509_read_value (resp->basicresp, name, &sa, 0);
+      ret = _gnutls_x509_read_value (resp->basicresp, name, &sa);
       if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
        return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
       else if (ret < 0)
@@ -1655,7 +1638,7 @@ gnutls_ocsp_resp_get_extension (gnutls_ocsp_resp_t resp,
     {
       snprintf (name, sizeof (name),
                "tbsResponseData.responseExtensions.?%u.extnID", indx + 1);
-      ret = _gnutls_x509_read_value (resp->basicresp, name, oid, 0);
+      ret = _gnutls_x509_read_value (resp->basicresp, name, oid);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -1667,7 +1650,7 @@ gnutls_ocsp_resp_get_extension (gnutls_ocsp_resp_t resp,
     {
       snprintf (name, sizeof (name),
                "tbsResponseData.responseExtensions.?%u.extnValue", indx + 1);
-      ret = _gnutls_x509_read_value (resp->basicresp, name, data, 0);
+      ret = _gnutls_x509_read_value (resp->basicresp, name, data);
       if (ret != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
@@ -1701,7 +1684,6 @@ gnutls_ocsp_resp_get_nonce (gnutls_ocsp_resp_t resp,
                            gnutls_datum_t *nonce)
 {
   int ret;
-  size_t l = 0;
   gnutls_datum_t tmp;
 
   ret = get_extension (resp->basicresp, "tbsResponseData.responseExtensions",
@@ -1713,32 +1695,16 @@ gnutls_ocsp_resp_get_nonce (gnutls_ocsp_resp_t resp,
       return ret;
     }
 
-  ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
-                                         NULL, &l);
-  if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+  ret = _gnutls_x509_decode_string (NULL, tmp.data, (size_t) tmp.size,
+                                   nonce);
+  if (ret < 0)
     {
       gnutls_assert ();
       gnutls_free (tmp.data);
       return ret;
     }
 
-  nonce->data = gnutls_malloc (l);
-  if (nonce->data == NULL)
-    {
-      gnutls_assert ();
-      gnutls_free (tmp.data);
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
-                                         nonce->data, &l);
   gnutls_free (tmp.data);
-  if (ret != GNUTLS_E_SUCCESS)
-    {
-      gnutls_assert ();
-      return ret;
-    }
-  nonce->size = l;
 
   return GNUTLS_E_SUCCESS;
 }
@@ -1761,7 +1727,7 @@ gnutls_ocsp_resp_get_signature_algorithm 
(gnutls_ocsp_resp_t resp)
   gnutls_datum_t sa;
 
   ret = _gnutls_x509_read_value (resp->basicresp,
-                                "signatureAlgorithm.algorithm", &sa, 0);
+                                "signatureAlgorithm.algorithm", &sa);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1797,7 +1763,7 @@ gnutls_ocsp_resp_get_signature (gnutls_ocsp_resp_t resp,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = _gnutls_x509_read_value (resp->basicresp, "signature", sig, 2);
+  ret = _gnutls_x509_read_string (resp->basicresp, "signature", sig, 
RV_BIT_STRING);
   if (ret != GNUTLS_E_SUCCESS)
     {
       gnutls_assert ();
diff --git a/lib/x509/output.c b/lib/x509/output.c
index 18db408..a77484b 100644
--- a/lib/x509/output.c
+++ b/lib/x509/output.c
@@ -882,7 +882,8 @@ static void
 print_extensions (gnutls_buffer_st * str, const char *prefix, int type,
                   cert_type_t cert)
 {
-  int i, err;
+  unsigned i, j;
+  int err;
   int san_idx = 0;
   int ian_idx = 0;
   int proxy_idx = 0;
@@ -957,6 +958,39 @@ print_extensions (gnutls_buffer_st * str, const char 
*prefix, int type,
 
           ski_idx++;
         }
+      else if (strcmp (oid, "2.5.29.32") == 0)
+        {
+          struct gnutls_certificate_policy_st policy;
+          const char* name;
+          int x;
+
+          for (x=0;;x++)
+            {
+              err = gnutls_x509_crt_get_policy (cert.crt, x, &policy, 
&critical);
+              if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+                break;
+              
+              if (err < 0)
+                {
+                  addf (str, "error: certificate policy: %s\n", 
gnutls_strerror(err));
+                  break;
+                }
+
+              addf (str, "%s\t\tCertificate Policies (%s):\n", prefix, 
critical ? _("critical") : _("not critical"));
+              addf (str, "%s\t\t\t%s\n", prefix, policy.policy_oid);
+              for (j=0;j<policy.qualifiers;j++)
+                {
+                  if (policy.qualifier_type[j]==GNUTLS_X509_QUALIFIER_URI)
+                    name = "URI";
+                  else if 
(policy.qualifier_type[j]==GNUTLS_X509_QUALIFIER_NOTICE)
+                    name = "Note";
+                  else name = "Unknown qualifier";
+                  addf (str, "%s\t\t\t\t%s: %s\n", prefix, name, 
policy.qualifier_data[j]);
+                }
+          
+              gnutls_certificate_policy_release (&policy);
+            }
+        }
       else if (strcmp (oid, "2.5.29.35") == 0)
         {
 
@@ -1532,11 +1566,12 @@ print_other (gnutls_buffer_st * str, gnutls_x509_crt_t 
cert, int notsigned)
 static void
 print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
 {
+int err;
+
   /* Subject. */
   {
     char *dn;
     size_t dn_size = 0;
-    int err;
 
     err = gnutls_x509_crt_get_dn (cert, NULL, &dn_size);
     if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
@@ -1563,7 +1598,6 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t 
cert)
   {
     char *dn;
     size_t dn_size = 0;
-    int err;
 
     err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &dn_size);
     if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
@@ -1598,8 +1632,6 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t 
cert)
 
   /* Signature Algorithm. */
   {
-    int err;
-
     err = gnutls_x509_crt_get_signature_algorithm (cert);
     if (err < 0)
       addf (str, "unknown signature algorithm (%s), ", gnutls_strerror (err));
@@ -1651,7 +1683,6 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t 
cert)
   {
     int pathlen;
     char *policyLanguage;
-    int err;
 
     err = gnutls_x509_crt_get_proxy (cert, NULL,
                                      &pathlen, &policyLanguage, NULL, NULL);
@@ -1675,7 +1706,6 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t 
cert)
   {
     char buffer[20];
     size_t size = sizeof (buffer);
-    int err;
 
     err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
                                            buffer, &size);
diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c
index 380f3fc..a980ce2 100644
--- a/lib/x509/pkcs12.c
+++ b/lib/x509/pkcs12.c
@@ -68,7 +68,7 @@ _decode_pkcs12_auth_safe (ASN1_TYPE pkcs12, ASN1_TYPE * 
authen_safe,
    */
 
   result =
-    _gnutls_x509_read_value (pkcs12, "authSafe.content", &auth_safe, 1);
+    _gnutls_x509_read_string (pkcs12, "authSafe.content", &auth_safe, 
RV_OCTET_STRING);
   if (result < 0)
     {
       gnutls_assert ();
@@ -373,8 +373,8 @@ _pkcs12_decode_safe_contents (const gnutls_datum_t * 
content,
   int len, result;
   int bag_type;
   gnutls_datum_t attr_val;
+  gnutls_datum_t t;
   int count = 0, i, attributes, j;
-  size_t size;
 
   /* Step 1. Extract the SEQUENCE.
    */
@@ -437,7 +437,7 @@ _pkcs12_decode_safe_contents (const gnutls_datum_t * 
content,
 
       snprintf (root, sizeof (root), "?%u.bagValue", i + 1);
 
-      result = _gnutls_x509_read_value (c2, root, &bag->element[i].data, 0);
+      result = _gnutls_x509_read_value (c2, root, &bag->element[i].data);
       if (result < 0)
         {
           gnutls_assert ();
@@ -495,38 +495,39 @@ _pkcs12_decode_safe_contents (const gnutls_datum_t * 
content,
 
             if (strcmp (oid, KEY_ID_OID) == 0)
               {
-                size = attr_val.size;
-
                 result =
-                  _gnutls_x509_decode_octet_string (NULL, attr_val.data, size,
-                                                    attr_val.data, &size);
-                attr_val.size = size;
+                  _gnutls_x509_decode_string (NULL, attr_val.data, 
attr_val.size, &t);
+                _gnutls_free_datum (&attr_val);
                 if (result < 0)
                   {
-                    _gnutls_free_datum (&attr_val);
                     gnutls_assert ();
                     _gnutls_debug_log
                       ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
                     continue;
                   }
+                
+                attr_val.data = t.data;
+                attr_val.size = t.size;
+                
                 bag->element[i].local_key_id = attr_val;
               }
             else if (strcmp (oid, FRIENDLY_NAME_OID) == 0)
               {
-                size = attr_val.size;
                 result =
-                  _gnutls_x509_decode_octet_string ("BMPString",
-                                                    attr_val.data, size,
-                                                    attr_val.data, &size);
-                attr_val.size = size;
+                  _gnutls_x509_decode_string ("BMPString",
+                                              attr_val.data, attr_val.size, 
&t);
+                _gnutls_free_datum (&attr_val);
                 if (result < 0)
                   {
-                    _gnutls_free_datum (&attr_val);
                     gnutls_assert ();
                     _gnutls_debug_log
                       ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
                     continue;
                   }
+
+                attr_val.data = t.data;
+                attr_val.size = t.size;
+
                 bag->element[i].friendly_name =
                   ucs2_to_ascii ((char*)attr_val.data, attr_val.size);
               }
@@ -566,7 +567,7 @@ _parse_safe_contents (ASN1_TYPE sc, const char *sc_name,
   /* Step 1. Extract the content.
    */
 
-  result = _gnutls_x509_read_value (sc, sc_name, &content, 1);
+  result = _gnutls_x509_read_string (sc, sc_name, &content, RV_OCTET_STRING);
   if (result < 0)
     {
       gnutls_assert ();
@@ -665,7 +666,7 @@ gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12,
   bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
   bag->bag_elements = 1;
 
-  result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data, 0);
+  result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data);
   if (result < 0)
     {
       gnutls_assert ();
@@ -1048,7 +1049,7 @@ gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const 
char *pass)
   /* Read the salt from the structure.
    */
   result =
-    _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0);
+    _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt);
   if (result != ASN1_SUCCESS)
     {
       gnutls_assert ();
diff --git a/lib/x509/pkcs12_bag.c b/lib/x509/pkcs12_bag.c
index 38d01e9..64db1bf 100644
--- a/lib/x509/pkcs12_bag.c
+++ b/lib/x509/pkcs12_bag.c
@@ -195,7 +195,7 @@ _pkcs12_decode_crt_bag (gnutls_pkcs12_bag_type_t type,
           goto cleanup;
         }
 
-      ret = _gnutls_x509_read_value (c2, "certValue", out, 1);
+      ret = _gnutls_x509_read_string (c2, "certValue", out, RV_OCTET_STRING);
       if (ret < 0)
         {
           gnutls_assert ();
@@ -221,7 +221,7 @@ _pkcs12_decode_crt_bag (gnutls_pkcs12_bag_type_t type,
           goto cleanup;
         }
 
-      ret = _gnutls_x509_read_value (c2, "crlValue", out, 1);
+      ret = _gnutls_x509_read_string (c2, "crlValue", out, RV_OCTET_STRING);
       if (ret < 0)
         {
           gnutls_assert ();
@@ -247,7 +247,7 @@ _pkcs12_decode_crt_bag (gnutls_pkcs12_bag_type_t type,
           goto cleanup;
         }
 
-      ret = _gnutls_x509_read_value (c2, "secretValue", out, 1);
+      ret = _gnutls_x509_read_string (c2, "secretValue", out, RV_OCTET_STRING);
       if (ret < 0)
         {
           gnutls_assert ();
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index 1a81971..5e95bb4 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -300,7 +300,7 @@ _gnutls_privkey_decode_ecc_key (const gnutls_datum_t * 
raw_key,
     }
 
   /* read the public key */
-  ret = _gnutls_x509_read_value(pkey_asn, "publicKey", &out, 2);
+  ret = _gnutls_x509_read_string(pkey_asn, "publicKey", &out, RV_BIT_STRING);
   if (ret < 0)
     {
       gnutls_assert();
diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c
index 27c8da0..ae58d5a 100644
--- a/lib/x509/privkey_pkcs8.c
+++ b/lib/x509/privkey_pkcs8.c
@@ -1055,7 +1055,7 @@ _decode_pkcs8_rsa_key (ASN1_TYPE pkcs8_asn, 
gnutls_x509_privkey_t pkey)
   int ret;
   gnutls_datum_t tmp;
 
-  ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0);
+  ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1084,7 +1084,7 @@ _decode_pkcs8_ecc_key (ASN1_TYPE pkcs8_asn, 
gnutls_x509_privkey_t pkey)
   int ret;
   gnutls_datum_t tmp;
 
-  ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0);
+  ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1114,7 +1114,7 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, 
gnutls_x509_privkey_t pkey)
   int ret;
   gnutls_datum_t tmp;
 
-  ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0);
+  ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1132,7 +1132,7 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, 
gnutls_x509_privkey_t pkey)
 
   ret =
     _gnutls_x509_read_value (pkcs8_asn, "privateKeyAlgorithm.parameters",
-                             &tmp, 0);
+                             &tmp);
   if (ret < 0)
     {
       gnutls_assert ();
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 1549eda..235cce7 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -297,9 +297,10 @@ gnutls_x509_crt_get_issuer_dn (gnutls_x509_crt_t cert, 
char *buf,
  * is not specified the output is always null terminated, although the
  * @buf_size will not include the null character.
  *
- * Returns: GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
- *   long enough, and in that case the @buf_size will be updated
- *   with the required size.  On success 0 is returned.
+ * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
+ *   long enough, and in that case the @buf_size will be updated with
+ *   the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if there 
+ *   are no data in the current index. On success 0 is returned.
  **/
 int
 gnutls_x509_crt_get_issuer_dn_by_oid (gnutls_x509_crt_t cert,
@@ -332,9 +333,10 @@ gnutls_x509_crt_get_issuer_dn_by_oid (gnutls_x509_crt_t 
cert,
  * returned will be null terminated, although @oid_size will not
  * account for the trailing null.
  *
- * Returns: GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
- *   long enough, and in that case the @oid_size will be updated
- *   with the required size.  On success 0 is returned.
+ * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
+ *   long enough, and in that case the @buf_size will be updated with
+ *   the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if there 
+ *   are no data in the current index. On success 0 is returned.
  **/
 int
 gnutls_x509_crt_get_issuer_dn_oid (gnutls_x509_crt_t cert,
@@ -407,9 +409,10 @@ gnutls_x509_crt_get_dn (gnutls_x509_crt_t cert, char *buf,
  * is not specified the output is always null terminated, although the
  * @buf_size will not include the null character.
  *
- * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
- *   not long enough, and in that case the *buf_size will be updated
- *   with the required size.  On success 0 is returned.
+ * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
+ *   long enough, and in that case the @buf_size will be updated with
+ *   the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if there 
+ *   are no data in the current index. On success 0 is returned.
  **/
 int
 gnutls_x509_crt_get_dn_by_oid (gnutls_x509_crt_t cert, const char *oid,
@@ -441,9 +444,10 @@ gnutls_x509_crt_get_dn_by_oid (gnutls_x509_crt_t cert, 
const char *oid,
  * returned will be null terminated, although @oid_size will not
  * account for the trailing null.
  *
- * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
- *   not long enough, and in that case the @oid_size will be updated
- *   with the required size.  On success 0 is returned.
+ * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
+ *   long enough, and in that case the @buf_size will be updated with
+ *   the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if there 
+ *   are no data in the current index. On success 0 is returned.
  **/
 int
 gnutls_x509_crt_get_dn_oid (gnutls_x509_crt_t cert,
@@ -1756,6 +1760,264 @@ gnutls_x509_crt_get_proxy (gnutls_x509_crt_t cert,
 }
 
 /**
+ * gnutls_certificate_policy_release:
+ * @policy: a certificate policy
+ *
+ * This function will deinitialize all memory associated with the provided
+ * @policy. The policy is allocated using gnutls_x509_crt_get_policy().
+ *
+ **/
+void gnutls_certificate_policy_release(struct gnutls_certificate_policy_st* 
policy)
+{
+unsigned i;
+
+  gnutls_free(policy->policy_oid);
+  for (i=0;i<policy->qualifiers;i++)
+    gnutls_free(policy->qualifier_data[i]);
+}
+
+static int decode_user_notice(const void* data, size_t size, char** txt)
+{
+  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+  int ret, len;
+  char choice_type[64];
+  char name[128];
+  gnutls_datum_t td, td2;
+
+  ret = asn1_create_element
+    (_gnutls_get_pkix (), "PKIX1.UserNotice", &c2);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  ret = asn1_der_decoding (&c2, data, size, NULL);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+  
+  len = sizeof(choice_type);
+  ret = asn1_read_value(c2, "explicitText", choice_type, &len);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  if (strcmp(choice_type, "utf8String") != 0 && strcmp(choice_type, 
"IA5String") != 0 &&
+      strcmp(choice_type, "bmpString") != 0)
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_PARSING_ERROR;
+      goto cleanup;
+    }
+
+  snprintf (name, sizeof (name), "explicitText.%s", choice_type);
+
+  ret = _gnutls_x509_read_value(c2, name, &td);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  if (strcmp(choice_type, "bmpString") == 0)
+    { /* convert to UTF-8 */
+      ret = _gnutls_ucs2_to_utf8(td.data, td.size, &td2);
+      _gnutls_free_datum(&td);
+      if (ret < 0)
+        {
+          gnutls_assert();
+          goto cleanup;
+        }
+        
+      td.data = td2.data;
+      td.size = td2.size;
+    }
+  else
+    {
+      /* _gnutls_x509_read_value allows that */
+      td.data[td.size] = 0;
+    }
+
+  *txt = (void*)td.data;
+  ret = 0;
+
+cleanup:
+  asn1_delete_structure (&c2);
+  return ret;
+
+}
+
+/**
+ * gnutls_x509_crt_get_policy:
+ * @cert: should contain a #gnutls_x509_crt_t structure
+ * @indx: This specifies which policy to return. Use (0) to get the first one.
+ * @policy: A pointer to a policy structure.
+ * @critical: will be non (0) if the extension is marked as critical
+ *
+ * This function will extract the certificate policy specified by the
+ * given index. 
+ *
+ * If @oid is null then only the size will be filled. The @oid
+ * returned will be null terminated, although @oid_size will not
+ * account for the trailing null.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, 
%GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
+ * if the extension is not present, otherwise a negative error value.
+ **/
+int
+gnutls_x509_crt_get_policy (gnutls_x509_crt_t crt, int indx, struct 
gnutls_certificate_policy_st* policy, unsigned int *critical)
+{
+  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+  char tmpstr[128];
+  char tmpoid[MAX_OID_SIZE];
+  gnutls_datum_t tmpd = {NULL, 0};
+  int ret, len;
+  unsigned i;
+ 
+  if (crt == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+    
+  memset(policy, 0, sizeof(*policy));
+
+  if ((ret =
+       _gnutls_x509_crt_get_extension (crt, "2.5.29.32", 0, &tmpd,
+                                       critical)) < 0)
+    {
+      return ret;
+    }
+
+  if (tmpd.size == 0 || tmpd .data == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+    }
+
+  ret = asn1_create_element
+    (_gnutls_get_pkix (), "PKIX1.certificatePolicies", &c2);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  ret = asn1_der_decoding (&c2, tmpd.data, tmpd.size, NULL);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+  _gnutls_free_datum (&tmpd);
+
+  indx++;
+  /* create a string like "?1"
+   */
+  snprintf (tmpstr, sizeof (tmpstr), "?%u.policyIdentifier", indx);
+
+  ret = _gnutls_x509_read_value(c2, tmpstr, &tmpd);
+  
+  if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
+    ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+  
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+  policy->policy_oid = (void*)tmpd.data;
+  tmpd.data = NULL;
+  
+  for (i=0;i<GNUTLS_MAX_QUALIFIERS;i++)
+    {
+      gnutls_datum_t td;
+
+      snprintf (tmpstr, sizeof (tmpstr), 
"?%u.policyQualifiers.?%u.policyQualifierId", indx, i+1);
+
+      len = sizeof(tmpoid);
+      ret = asn1_read_value(c2, tmpstr, tmpoid, &len);
+      
+      if (ret == ASN1_ELEMENT_NOT_FOUND && i > 0)
+        break; /* finished */
+      
+      if (ret != ASN1_SUCCESS)
+        {
+          gnutls_assert();
+          ret = _gnutls_asn2err (ret);
+          goto cleanup;
+        }
+
+      if (strcmp(tmpoid, "1.3.6.1.5.5.7.2.1") == 0)
+        {
+          snprintf (tmpstr, sizeof (tmpstr), 
"?%u.policyQualifiers.?%u.qualifier", indx, i+1);
+
+          ret = _gnutls_x509_read_string(c2, tmpstr, &td, RV_IA5STRING);
+          if (ret < 0)
+            {
+              gnutls_assert();
+              goto full_cleanup;
+            }
+
+          policy->qualifier_data[i] = (void*)td.data;
+          td.data = NULL;
+          policy->qualifier_type[i] = GNUTLS_X509_QUALIFIER_URI;
+        }
+      else if (strcmp(tmpoid, "1.3.6.1.5.5.7.2.2") == 0)
+        {
+          snprintf (tmpstr, sizeof (tmpstr), 
"?%u.policyQualifiers.?%u.qualifier", indx, i+1);
+
+          ret = _gnutls_x509_read_string(c2, tmpstr, &td, RV_RAW);
+          if (ret < 0)
+            {
+              gnutls_assert();
+              goto full_cleanup;
+            }
+
+          ret = decode_user_notice(td.data, td.size, 
&policy->qualifier_data[i]);
+          gnutls_free(td.data);
+          td.data = NULL;
+
+          if (ret < 0)
+            {
+              gnutls_assert();
+              goto full_cleanup;
+            }
+
+          policy->qualifier_type[i] = GNUTLS_X509_QUALIFIER_NOTICE;
+        }
+      else
+        policy->qualifier_type[i] = GNUTLS_X509_QUALIFIER_UNKNOWN;
+      
+      policy->qualifiers++;
+    
+    }
+  
+
+  ret = 0;
+  goto cleanup;
+  
+full_cleanup:
+  gnutls_certificate_policy_release(policy);
+
+cleanup:
+  _gnutls_free_datum (&tmpd);
+  asn1_delete_structure (&c2);
+  return ret;
+}
+
+
+/**
  * gnutls_x509_crt_get_extension_by_oid:
  * @cert: should contain a #gnutls_x509_crt_t structure
  * @oid: holds an Object Identified in null terminated string
@@ -3443,8 +3705,8 @@ gnutls_x509_crt_get_subject_unique_id (gnutls_x509_crt_t 
crt, char *buf,
   gnutls_datum_t datum = { NULL, 0 };
 
   result =
-    _gnutls_x509_read_value (crt->cert, "tbsCertificate.subjectUniqueID",
-                             &datum, 2);
+    _gnutls_x509_read_string (crt->cert, "tbsCertificate.subjectUniqueID",
+                             &datum, RV_BIT_STRING);
 
   if (datum.size > *buf_size)
     {                           /* then we're not going to fit */
@@ -3489,8 +3751,8 @@ gnutls_x509_crt_get_issuer_unique_id (gnutls_x509_crt_t 
crt, char *buf,
   gnutls_datum_t datum = { NULL, 0 };
 
   result =
-    _gnutls_x509_read_value (crt->cert, "tbsCertificate.issuerUniqueID",
-                             &datum, 2);
+    _gnutls_x509_read_string (crt->cert, "tbsCertificate.issuerUniqueID",
+                             &datum, RV_BIT_STRING);
 
   if (datum.size > *buf_size)
     {                           /* then we're not going to fit */


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]