summaryrefslogtreecommitdiff
path: root/lib/x509
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2012-11-18 19:31:54 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2012-11-18 19:31:54 +0100
commit9e02a17f503668551356bdd10489b93c447834e4 (patch)
tree3ab0e52f14dca48efc1d56317a4cb2a259deb456 /lib/x509
parent96c38a6c89fe0b6f7d826c3588479ec861811054 (diff)
downloadgnutls-9e02a17f503668551356bdd10489b93c447834e4.tar.gz
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.
Diffstat (limited to 'lib/x509')
-rw-r--r--lib/x509/common.c193
-rw-r--r--lib/x509/common.h26
-rw-r--r--lib/x509/crl.c2
-rw-r--r--lib/x509/dn.c6
-rw-r--r--lib/x509/extensions.c6
-rw-r--r--lib/x509/mpi.c4
-rw-r--r--lib/x509/ocsp.c90
-rw-r--r--lib/x509/output.c44
-rw-r--r--lib/x509/pkcs12.c37
-rw-r--r--lib/x509/pkcs12_bag.c6
-rw-r--r--lib/x509/privkey.c2
-rw-r--r--lib/x509/privkey_pkcs8.c8
-rw-r--r--lib/x509/x509.c294
13 files changed, 522 insertions, 196 deletions
diff --git a/lib/x509/common.c b/lib/x509/common.c
index d577f8ae4a..76ff429d42 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,7 +300,7 @@ _gnutls_x509_oid_data2string (const char *oid, void *value,
asn1_delete_structure (&tmpasn);
}
else
- { /* CHOICE */
+ { /* choice */
int non_printable = 0, teletex = 0;
str[len] = 0;
@@ -335,7 +335,7 @@ _gnutls_x509_oid_data2string (const char *oid, void *value,
* characters then treat it as printable.
*/
for (i = 0; i < len; i++)
- if (!isascii (str[i]))
+ if (!isprint (str[i]))
ascii = 1;
if (ascii == 0)
@@ -664,7 +664,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 +853,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 +885,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 +907,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 +974,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 +993,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 +1205,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 +1235,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 +1496,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 1ee919435b..4b38884434 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 8acc64ca82..f156b43132 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 9c6096193d..9506969f5a 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 a429bfea27..c251b0d727 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 c9d3058932..7792c588a1 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 8756431a71..87a250317c 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 18db408204..a77484bae6 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 380f3fc9b0..a980ce2d75 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 38d01e9c73..64db1bf904 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 1a81971c3a..5e95bb4734 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 27c8da00cc..ae58d5a12f 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 1549eda208..235cce7062 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 */