summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-09-10 16:02:12 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-09-11 18:08:21 +0200
commit469f8fbead2acb60c215be1ddb6d769cda78d1af (patch)
tree5b71fc552702a940b1787f570570452827ceb5ef
parent0aefb946f6b25a617412316b05affcd7811da2be (diff)
downloadgnutls-469f8fbead2acb60c215be1ddb6d769cda78d1af.tar.gz
allow retrieving extensions in a trust module using GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/includes/gnutls/pkcs11.h12
-rw-r--r--lib/includes/gnutls/x509.h13
-rw-r--r--lib/libgnutls.map3
-rw-r--r--lib/pkcs11.c89
-rw-r--r--lib/pkcs11_int.c41
-rw-r--r--lib/pkcs11_int.h9
-rw-r--r--lib/x509/common.h1
-rw-r--r--lib/x509/output.c1217
-rw-r--r--lib/x509/x509_ext.c87
10 files changed, 656 insertions, 818 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index bae022a698..6acaf8f9b5 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -89,7 +89,7 @@ COBJECTS += crypto-selftests.c crypto-selftests-pk.c
endif
if ENABLE_PKCS11
-COBJECTS += pkcs11.c pkcs11_privkey.c pkcs11_write.c pkcs11_secret.c \
+COBJECTS += pkcs11.c pkcs11x.c pkcs11_privkey.c pkcs11_write.c pkcs11_secret.c \
pkcs11_int.c
endif
diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h
index 8fd121dab6..93d7ae1f00 100644
--- a/lib/includes/gnutls/pkcs11.h
+++ b/lib/includes/gnutls/pkcs11.h
@@ -108,6 +108,7 @@ void gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj,
* @GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE: The object must be present in a marked as trusted module.
* @GNUTLS_PKCS11_OBJ_FLAG_MARK_CA: Mark the object as a CA.
* @GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP: Mark the generated key pair as wrapping and unwrapping keys.
+ * @GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT: When an issuer is requested, override its extensions with the ones present in the trust module.
*
* Enumeration of different PKCS #11 object flags.
*/
@@ -125,7 +126,8 @@ typedef enum gnutls_pkcs11_obj_flags {
GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE = (1<<10),
GNUTLS_PKCS11_OBJ_FLAG_MARK_CA = (1<<11),
GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP = (1<<12),
- GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY = (1<<13)
+ GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY = (1<<13),
+ GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT = (1<<14)
} gnutls_pkcs11_obj_flags;
/**
@@ -279,7 +281,8 @@ typedef enum {
GNUTLS_PKCS11_OBJ_PUBKEY,
GNUTLS_PKCS11_OBJ_PRIVKEY,
GNUTLS_PKCS11_OBJ_SECRET_KEY,
- GNUTLS_PKCS11_OBJ_DATA
+ GNUTLS_PKCS11_OBJ_DATA,
+ GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION
} gnutls_pkcs11_obj_type_t;
int
@@ -333,6 +336,11 @@ gnutls_pkcs11_obj_get_type(gnutls_pkcs11_obj_t obj);
const char *gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_type_t type);
int
+gnutls_pkcs11_obj_get_exts(gnutls_pkcs11_obj_t obj,
+ struct gnutls_x509_ext_st **exts, unsigned int *exts_size,
+ unsigned int flags);
+
+int
gnutls_pkcs11_obj_get_flags(gnutls_pkcs11_obj_t obj, unsigned int *oflags);
char *gnutls_pkcs11_obj_flags_get_str(unsigned int flags);
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index 3eeab0eb1d..14038b6f2d 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -1354,6 +1354,19 @@ void gnutls_certificate_set_trust_list
(gnutls_certificate_credentials_t res,
gnutls_x509_trust_list_t tlist, unsigned flags);
+typedef struct gnutls_x509_ext_st {
+ char *oid;
+ unsigned int critical;
+ gnutls_datum_t data;
+} gnutls_x509_ext_st;
+
+void gnutls_x509_ext_deinit(gnutls_x509_ext_st *ext);
+
+int
+gnutls_x509_ext_print(gnutls_x509_ext_st *exts, unsigned int exts_size,
+ gnutls_certificate_print_formats_t format,
+ gnutls_datum_t * out);
+
/* *INDENT-OFF* */
#ifdef __cplusplus
}
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 94f99642fc..6fc2817484 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1026,6 +1026,9 @@ GNUTLS_3_1_0 {
gnutls_x509_trust_list_verify_crt2;
gnutls_x509_crt_get_extension_by_oid2;
gnutls_x509_crq_get_extension_by_oid2;
+ gnutls_pkcs11_obj_get_exts;
+ gnutls_x509_ext_deinit;
+ gnutls_x509_ext_print;
} GNUTLS_3_0_0;
GNUTLS_FIPS140 {
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
index a7c60296b7..2e2ea561ad 100644
--- a/lib/pkcs11.c
+++ b/lib/pkcs11.c
@@ -36,13 +36,13 @@
#include <pin.h>
#include <pkcs11_int.h>
#include <p11-kit/p11-kit.h>
+#include <p11-kit/pkcs11x.h>
#include <p11-kit/pin.h>
+
#include <atfork.h>
#define MAX_PROVIDERS 16
-/* XXX: try to eliminate this */
-#define MAX_CERT_SIZE 32*1024
#define MAX_SLOTS 48
extern void *_gnutls_pkcs11_mutex;
@@ -1197,6 +1197,9 @@ pkcs11_obj_import(ck_object_class_t class, gnutls_pkcs11_obj_t obj,
case CKO_CERTIFICATE:
obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
break;
+ case CKO_X_CERTIFICATE_EXTENSION:
+ obj->type = GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION;
+ break;
case CKO_PUBLIC_KEY:
obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
break;
@@ -1503,8 +1506,7 @@ pkcs11_import_object(ck_object_handle_t obj, ck_object_class_t class,
unsigned long category = 0;
char label_tmp[PKCS11_LABEL_SIZE];
char id_tmp[PKCS11_ID_SIZE];
- uint8_t *cert_data = NULL;
- gnutls_datum_t id, label, data;
+ gnutls_datum_t id, label, data = {NULL, 0};
/* now figure out flags */
fobj->flags = 0;
@@ -1571,7 +1573,6 @@ pkcs11_import_object(ck_object_handle_t obj, ck_object_class_t class,
label.size = a[0].value_len;
}
-
a[0].type = CKA_ID;
a[0].value = id_tmp;
a[0].value_len = sizeof(id_tmp);
@@ -1589,24 +1590,11 @@ pkcs11_import_object(ck_object_handle_t obj, ck_object_class_t class,
if (label.data == NULL && id.data == NULL)
return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
- cert_data = gnutls_malloc(MAX_CERT_SIZE);
- if (cert_data == NULL) {
+ rv = pkcs11_get_attribute_avalue
+ (sinfo->module, sinfo->pks, obj, CKA_VALUE, &data);
+ if (rv != CKR_OK) {
gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- a[0].type = CKA_VALUE;
- a[0].value = cert_data;
- a[0].value_len = MAX_CERT_SIZE;
-
- rv = pkcs11_get_attribute_value
- (sinfo->module, sinfo->pks, obj, a, 1);
- if (rv == CKR_OK) {
- data.data = a[0].value;
- data.size = a[0].value_len;
- } else {
- data.data = NULL;
- data.size = 0;
+ /* data will be null */
}
if (class == CKO_PUBLIC_KEY) {
@@ -1633,7 +1621,7 @@ pkcs11_import_object(ck_object_handle_t obj, ck_object_class_t class,
ret = 0;
cleanup:
- gnutls_free(cert_data);
+ gnutls_free(data.data);
return ret;
}
@@ -2578,7 +2566,6 @@ find_objs_cb(struct pkcs11_session_info *sinfo,
unsigned j;
gnutls_datum_t id;
- class = -1;
for (j=0;j<count;j++) {
a[0].type = CKA_ID;
a[0].value = certid_tmp;
@@ -2593,7 +2580,6 @@ find_objs_cb(struct pkcs11_session_info *sinfo,
id.size = 0;
}
-
if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL ||
find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_MATCH) {
a[0].type = CKA_CLASS;
@@ -3094,6 +3080,8 @@ const char *gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_type_t type)
return "Secret key";
case GNUTLS_PKCS11_OBJ_DATA:
return "Data";
+ case GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION:
+ return "X.509 certificate extension";
case GNUTLS_PKCS11_OBJ_UNKNOWN:
default:
return "Unknown";
@@ -3116,10 +3104,10 @@ find_cert_cb(struct pkcs11_session_info *sinfo,
ck_object_handle_t obj;
unsigned long count, a_vals;
int found = 0, ret;
- uint8_t *cert_data = NULL;
struct find_cert_st *priv = input;
char label_tmp[PKCS11_LABEL_SIZE];
char id_tmp[PKCS11_ID_SIZE];
+ gnutls_datum_t data = {NULL, 0};
unsigned tries, i, finalized;
ck_bool_t trusted = 1;
@@ -3140,14 +3128,6 @@ find_cert_cb(struct pkcs11_session_info *sinfo,
priv->serial.size == 0)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
- /* search the token for the key ID */
-
- cert_data = gnutls_malloc(MAX_CERT_SIZE);
- if (cert_data == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
/* Find objects with given class and type */
if (priv->key_id.size > 0 && priv->dn.size > 0)
@@ -3234,28 +3214,37 @@ find_cert_cb(struct pkcs11_session_info *sinfo,
break;
}
- a[0].type = CKA_VALUE;
- a[0].value = cert_data;
- a[0].value_len = MAX_CERT_SIZE;
+ a[0].type = CKA_LABEL;
+ a[0].value = label_tmp;
+ a[0].value_len = sizeof(label_tmp);
- a[1].type = CKA_LABEL;
- a[1].value = label_tmp;
- a[1].value_len = sizeof(label_tmp);
+ a[1].type = CKA_ID;
+ a[1].value = id_tmp;
+ a[1].value_len = sizeof(id_tmp);
- a[2].type = CKA_ID;
- a[2].value = id_tmp;
- a[2].value_len = sizeof(id_tmp);
+ /* data will contain the certificate */
+ rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_VALUE, &data);
- if (pkcs11_get_attribute_value
+ if (rv == CKR_OK && pkcs11_get_attribute_value
(sinfo->module, sinfo->pks, obj, a,
- 3) == CKR_OK) {
- gnutls_datum_t id =
- { a[2].value, a[2].value_len };
- gnutls_datum_t data =
- { a[0].value, a[0].value_len };
+ 2) == CKR_OK) {
gnutls_datum_t label =
+ { a[0].value, a[0].value_len };
+ gnutls_datum_t id =
{ a[1].value, a[1].value_len };
+ if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT) {
+ gnutls_datum_t spki;
+ rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_PUBLIC_KEY_INFO, &spki);
+ if (rv == CKR_OK) {
+ ret = pkcs11_override_cert_exts(sinfo, &spki, &data);
+ if (ret < 0) {
+ gnutls_assert();
+ /* non fatal errors */
+ }
+ }
+ }
+
if (priv->need_import != 0) {
ret =
pkcs11_obj_import(class, priv->obj,
@@ -3315,7 +3304,7 @@ find_cert_cb(struct pkcs11_session_info *sinfo,
}
cleanup:
- gnutls_free(cert_data);
+ gnutls_free(data.data);
if (finalized == 0)
pkcs11_find_objects_final(sinfo);
diff --git a/lib/pkcs11_int.c b/lib/pkcs11_int.c
index 4359ec0fc7..9ff2d98bcf 100644
--- a/lib/pkcs11_int.c
+++ b/lib/pkcs11_int.c
@@ -33,6 +33,7 @@
#include <pin.h>
#include <pkcs11_int.h>
#include <p11-kit/p11-kit.h>
+#include <p11-kit/pkcs11.h>
#include <p11-kit/pin.h>
ck_rv_t
@@ -104,6 +105,46 @@ pkcs11_get_attribute_value(struct ck_function_list * module,
return (module)->C_GetAttributeValue(sess, object, templ, count);
}
+/* Returns only a single attribute value, but allocates its data
+ * Only the type needs to be set.
+ */
+ck_rv_t
+pkcs11_get_attribute_avalue(struct ck_function_list * module,
+ ck_session_handle_t sess,
+ ck_object_handle_t object,
+ ck_attribute_type_t type,
+ gnutls_datum_t *res)
+{
+ ck_rv_t rv;
+ struct ck_attribute templ;
+ void *t;
+
+ res->data = NULL;
+ res->size = 0;
+
+ templ.type = type;
+ templ.value = NULL;
+ templ.value_len = 0;
+ rv = (module)->C_GetAttributeValue(sess, object, &templ, 1);
+ if (rv == CKR_OK) {
+ if (templ.value_len == 0)
+ return rv;
+
+ templ.type = type;
+ t = gnutls_malloc(templ.value_len);
+ if (t == NULL)
+ return gnutls_assert_val(CKR_HOST_MEMORY);
+ templ.value = t;
+ rv = (module)->C_GetAttributeValue(sess, object, &templ, 1);
+ if (rv != CKR_OK) {
+ gnutls_free(t);
+ }
+ res->data = t;
+ res->size = templ.value_len;
+ }
+ return rv;
+}
+
ck_rv_t
pkcs11_get_mechanism_list(struct ck_function_list * module,
ck_slot_id_t slot_id,
diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h
index bbd4cf2116..3e932a95ea 100644
--- a/lib/pkcs11_int.h
+++ b/lib/pkcs11_int.h
@@ -94,6 +94,8 @@ int pkcs11_read_pubkey(struct ck_function_list *module,
ck_session_handle_t pks, ck_object_handle_t obj,
ck_key_type_t key_type, gnutls_datum_t * pubkey);
+int pkcs11_override_cert_exts(struct pkcs11_session_info *sinfo, gnutls_datum_t *spki, gnutls_datum_t *der);
+
int pkcs11_get_info(struct p11_kit_uri *info,
gnutls_pkcs11_obj_info_t itype, void *output,
size_t * output_size);
@@ -232,6 +234,13 @@ pkcs11_get_attribute_value(struct ck_function_list *module,
unsigned long count);
ck_rv_t
+pkcs11_get_attribute_avalue(struct ck_function_list * module,
+ ck_session_handle_t sess,
+ ck_object_handle_t object,
+ ck_attribute_type_t type,
+ gnutls_datum_t *res);
+
+ck_rv_t
pkcs11_get_mechanism_list(struct ck_function_list *module,
ck_slot_id_t slot_id,
ck_mechanism_type_t * mechanism_list,
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 044984841f..48340a12c0 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -214,6 +214,7 @@ int _gnutls_copy_data(gnutls_datum_t* str, uint8_t *out, size_t *out_size);
int _san_othername_to_virtual(const char *oid, size_t oid_size);
+int _gnutls_x509_decode_ext(const gnutls_datum_t *der, gnutls_x509_ext_st *out);
int x509_crt_to_raw_pubkey(const gnutls_datum_t * cert,
gnutls_datum_t * rpubkey);
diff --git a/lib/x509/output.c b/lib/x509/output.c
index bc6036f6fe..f7a6ad338f 100644
--- a/lib/x509/output.c
+++ b/lib/x509/output.c
@@ -98,7 +98,7 @@ char str_ip[64];
const char *p;
unsigned non_ascii = 0, i;
- if ((type == GNUTLS_SAN_DNSNAME
+ if ((type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_OTHERNAME_XMPP
|| type == GNUTLS_SAN_RFC822NAME
|| type == GNUTLS_SAN_URI) && sname != NULL && strlen(sname) != name->size) {
adds(str,
@@ -154,6 +154,10 @@ unsigned non_ascii = 0, i;
case GNUTLS_SAN_DN:
addf(str, _("%sdirectoryName: %.*s\n"), prefix, name->size, NON_NULL(name->data));
break;
+
+ case GNUTLS_SAN_OTHERNAME_XMPP:
+ addf(str, _("%sXMPP: %.*s\n"), prefix, name->size, NON_NULL(name->data));
+ break;
default:
addf(str, _("%sUnknown name: "), prefix);
_gnutls_buffer_hexprint(str, name->data, name->size);
@@ -161,7 +165,7 @@ unsigned non_ascii = 0, i;
}
}
-static void print_proxy(gnutls_buffer_st * str, gnutls_x509_crt_t cert)
+static void print_proxy(gnutls_buffer_st * str, gnutls_datum_t *der)
{
int pathlen;
char *policyLanguage;
@@ -169,8 +173,7 @@ static void print_proxy(gnutls_buffer_st * str, gnutls_x509_crt_t cert)
size_t npolicy;
int err;
- err = gnutls_x509_crt_get_proxy(cert, NULL,
- &pathlen, &policyLanguage,
+ err = gnutls_x509_ext_import_proxy(der, &pathlen, &policyLanguage,
&policy, &npolicy);
if (err < 0) {
addf(str, "error: get_proxy: %s\n", gnutls_strerror(err));
@@ -194,14 +197,16 @@ static void print_proxy(gnutls_buffer_st * str, gnutls_x509_crt_t cert)
_gnutls_buffer_hexprint(str, policy, npolicy);
adds(str, "\n");
}
+ gnutls_free(policy);
+ gnutls_free(policyLanguage);
}
-static void print_nc(gnutls_buffer_st * str, const char* prefix, gnutls_x509_crt_t cert)
+static void print_nc(gnutls_buffer_st * str, const char* prefix, gnutls_datum_t *der)
{
gnutls_x509_name_constraints_t nc;
int ret;
- unsigned critical, idx = 0;
+ unsigned idx = 0;
gnutls_datum_t name;
unsigned type;
char new_prefix[16];
@@ -210,7 +215,7 @@ static void print_nc(gnutls_buffer_st * str, const char* prefix, gnutls_x509_crt
if (ret < 0)
return;
- ret = gnutls_x509_crt_get_name_constraints(cert, nc, 0, &critical);
+ ret = gnutls_x509_ext_import_name_constraints(der, nc, 0);
if (ret < 0)
goto cleanup;
@@ -289,229 +294,97 @@ cleanup:
gnutls_x509_aia_deinit(aia);
}
-static void print_ski(gnutls_buffer_st * str, gnutls_x509_crt_t cert)
+static void print_ski(gnutls_buffer_st * str, gnutls_datum_t *der)
{
- char *buffer = NULL;
- size_t size = 0;
+ gnutls_datum_t id = {NULL, 0};
int err;
- err =
- gnutls_x509_crt_get_subject_key_id(cert, buffer, &size, NULL);
- if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
- addf(str, "error: get_subject_key_id: %s\n",
- gnutls_strerror(err));
- return;
- }
-
- buffer = gnutls_malloc(size);
- if (!buffer) {
- addf(str, "error: malloc: %s\n",
- gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
- return;
- }
-
- err =
- gnutls_x509_crt_get_subject_key_id(cert, buffer, &size, NULL);
+ err = gnutls_x509_ext_import_subject_key_id(der, &id);
if (err < 0) {
- gnutls_free(buffer);
- addf(str, "error: get_subject_key_id2: %s\n",
+ addf(str, "error: get_subject_key_id: %s\n",
gnutls_strerror(err));
return;
}
adds(str, "\t\t\t");
- _gnutls_buffer_hexprint(str, buffer, size);
+ _gnutls_buffer_hexprint(str, id.data, id.size);
adds(str, "\n");
- gnutls_free(buffer);
+ gnutls_free(id.data);
}
-#define TYPE_CRL 1
#define TYPE_CRT 2
#define TYPE_CRQ 3
-#define TYPE_PUBKEY 4
-
-#define TYPE_CRT_SAN TYPE_CRT
-#define TYPE_CRQ_SAN TYPE_CRQ
-#define TYPE_CRT_IAN 4
typedef union {
gnutls_x509_crt_t crt;
gnutls_x509_crq_t crq;
- gnutls_x509_crl_t crl;
- gnutls_pubkey_t pubkey;
} cert_type_t;
static void
-print_aki_gn_serial(gnutls_buffer_st * str, int type, cert_type_t cert)
+print_aki_gn_serial(gnutls_buffer_st * str, gnutls_x509_aki_t aki)
{
- char *buffer = NULL;
- char serial[128];
- size_t size = 0, serial_size = sizeof(serial);
+ gnutls_datum_t san, other_oid, serial;
unsigned int alt_type;
- gnutls_datum_t t;
int err;
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_authority_key_gn_serial(cert.crt,
- 0, NULL,
- &size,
- &alt_type,
- serial,
- &serial_size,
- NULL);
- else if (type == TYPE_CRL)
- err =
- gnutls_x509_crl_get_authority_key_gn_serial(cert.crl,
- 0, NULL,
- &size,
- &alt_type,
- serial,
- &serial_size,
- NULL);
- else {
- gnutls_assert();
- return;
- }
-
- if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
- addf(str, "error: get_authority_key_gn_serial: %s\n",
- gnutls_strerror(err));
- return;
- }
-
- buffer = gnutls_malloc(size);
- if (!buffer) {
- addf(str, "error: malloc: %s\n",
- gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
- return;
- }
-
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_authority_key_gn_serial(cert.crt,
- 0, buffer,
- &size,
- &alt_type,
- serial,
- &serial_size,
- NULL);
- else
- err =
- gnutls_x509_crl_get_authority_key_gn_serial(cert.crl,
- 0, buffer,
- &size,
- &alt_type,
- serial,
- &serial_size,
- NULL);
-
+ err =
+ gnutls_x509_aki_get_cert_issuer(aki,
+ 0, &alt_type, &san, &other_oid, &serial);
if (err < 0) {
- gnutls_free(buffer);
- addf(str, "error: get_authority_key_gn_serial2: %s\n",
+ addf(str, "error: gnutls_x509_aki_get_cert_issuer: %s\n",
gnutls_strerror(err));
return;
}
- t.data = (void*)buffer;
- t.size = size;
- print_name(str, "\t\t\t", alt_type, &t);
+ print_name(str, "\t\t\t", alt_type, &san);
adds(str, "\t\t\tserial: ");
- _gnutls_buffer_hexprint(str, serial, serial_size);
+ _gnutls_buffer_hexprint(str, serial.data, serial.size);
adds(str, "\n");
-
- gnutls_free(buffer);
}
-static void print_aki(gnutls_buffer_st * str, int type, cert_type_t cert)
+static void print_aki(gnutls_buffer_st * str, gnutls_datum_t *der)
{
- char *buffer = NULL;
- size_t size = 0;
int err;
+ gnutls_x509_aki_t aki;
+ gnutls_datum_t id;
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_authority_key_id(cert.crt, buffer,
- &size, NULL);
- else if (type == TYPE_CRL)
- err =
- gnutls_x509_crl_get_authority_key_id(cert.crl, buffer,
- &size, NULL);
- else {
- gnutls_assert();
- return;
- }
-
- if (err == GNUTLS_E_X509_UNSUPPORTED_EXTENSION) {
- /* Check if an alternative name is there */
- print_aki_gn_serial(str, type, cert);
+ err = gnutls_x509_aki_init(&aki);
+ if (err < 0) {
+ addf(str, "error: gnutls_x509_aki_init: %s\n",
+ gnutls_strerror(err));
return;
}
- if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
- addf(str, "error: get_authority_key_id: %s\n",
+ err = gnutls_x509_ext_import_authority_key_id(der, aki, 0);
+ if (err < 0) {
+ addf(str, "error: gnutls_x509_ext_import_authority_key_id: %s\n",
gnutls_strerror(err));
return;
}
- buffer = gnutls_malloc(size);
- if (!buffer) {
- addf(str, "error: malloc: %s\n",
- gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
+ err = gnutls_x509_aki_get_id(aki, &id);
+ if (err == GNUTLS_E_X509_UNSUPPORTED_EXTENSION) {
+ /* Check if an alternative name is there */
+ print_aki_gn_serial(str, aki);
return;
- }
-
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_authority_key_id(cert.crt, buffer,
- &size, NULL);
- else
- err =
- gnutls_x509_crl_get_authority_key_id(cert.crl, buffer,
- &size, NULL);
-
- if (err < 0) {
- gnutls_free(buffer);
- addf(str, "error: get_authority_key_id2: %s\n",
+ } else if (err < 0) {
+ addf(str, "error: gnutls_x509_aki_get_id: %s\n",
gnutls_strerror(err));
return;
}
-
+
adds(str, "\t\t\t");
- _gnutls_buffer_hexprint(str, buffer, size);
+ _gnutls_buffer_hexprint(str, id.data, id.size);
adds(str, "\n");
- gnutls_free(buffer);
+ gnutls_x509_aki_deinit(aki);
}
static void
-print_key_usage(gnutls_buffer_st * str, const char *prefix, int type,
- cert_type_t cert)
+print_key_usage2(gnutls_buffer_st * str, const char *prefix, unsigned int key_usage)
{
- unsigned int key_usage;
- int err;
-
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_key_usage(cert.crt, &key_usage,
- NULL);
- else if (type == TYPE_CRQ)
- err =
- gnutls_x509_crq_get_key_usage(cert.crq, &key_usage,
- NULL);
- else if (type == TYPE_PUBKEY)
- err = gnutls_pubkey_get_key_usage(cert.pubkey, &key_usage);
- else
- return;
-
- if (err < 0) {
- addf(str, "error: get_key_usage: %s\n",
- gnutls_strerror(err));
- return;
- }
-
if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)
addf(str, _("%sDigital signature.\n"), prefix);
if (key_usage & GNUTLS_KEY_NON_REPUDIATION)
@@ -533,8 +406,23 @@ print_key_usage(gnutls_buffer_st * str, const char *prefix, int type,
}
static void
-print_private_key_usage_period(gnutls_buffer_st * str, const char *prefix,
- int type, cert_type_t cert)
+print_key_usage(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
+{
+ unsigned int key_usage;
+ int err;
+
+ err = gnutls_x509_ext_import_key_usage(der, &key_usage);
+ if (err < 0) {
+ addf(str, "error: get_key_usage: %s\n",
+ gnutls_strerror(err));
+ return;
+ }
+
+ print_key_usage2(str, prefix, key_usage);
+}
+
+static void
+print_private_key_usage_period(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
{
time_t activation, expiration;
int err;
@@ -542,21 +430,7 @@ print_private_key_usage_period(gnutls_buffer_st * str, const char *prefix,
struct tm t;
size_t max;
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_private_key_usage_period(cert.crt,
- &activation,
- &expiration,
- NULL);
- else if (type == TYPE_CRQ)
- err =
- gnutls_x509_crq_get_private_key_usage_period(cert.crq,
- &activation,
- &expiration,
- NULL);
- else
- return;
-
+ err = gnutls_x509_ext_import_private_key_usage_period(der, &activation, &expiration);
if (err < 0) {
addf(str, "error: get_private_key_usage_period: %s\n",
gnutls_strerror(err));
@@ -585,166 +459,115 @@ print_private_key_usage_period(gnutls_buffer_st * str, const char *prefix,
}
-static void print_crldist(gnutls_buffer_st * str, gnutls_x509_crt_t cert)
+static void print_crldist(gnutls_buffer_st * str, gnutls_datum_t *der)
{
- char *buffer = NULL;
- size_t size;
- gnutls_datum_t t;
int err;
int indx;
+ gnutls_x509_crl_dist_points_t dp;
+ unsigned int flags, type;
+ gnutls_datum_t dist;
+
+ err = gnutls_x509_crl_dist_points_init(&dp);
+ if (err < 0) {
+ addf(str, "error: gnutls_x509_crl_dist_points_init: %s\n",
+ gnutls_strerror(err));
+ return;
+ }
+
+ err = gnutls_x509_ext_import_crl_dist_points(der, dp, 0);
+ if (err < 0) {
+ addf(str, "error: gnutls_x509_ext_import_crl_dist_points: %s\n",
+ gnutls_strerror(err));
+ return;
+ }
for (indx = 0;; indx++) {
- size = 0;
err =
- gnutls_x509_crt_get_crl_dist_points(cert, indx, buffer,
- &size, NULL, NULL);
+ gnutls_x509_crl_dist_points_get(dp, indx, &type, &dist, &flags);
if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
return;
- if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ else if (err < 0) {
addf(str, "error: get_crl_dist_points: %s\n",
gnutls_strerror(err));
return;
}
- buffer = gnutls_malloc(size);
- if (!buffer) {
- addf(str, "error: malloc: %s\n",
- gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
- return;
- }
-
- err =
- gnutls_x509_crt_get_crl_dist_points(cert, indx, buffer,
- &size, NULL, NULL);
- if (err < 0) {
- gnutls_free(buffer);
- addf(str, "error: get_crl_dist_points2: %s\n",
- gnutls_strerror(err));
- return;
- }
-
- t.data = (void*)buffer;
- t.size = size;
- print_name(str, "\t\t\t", err, &t);
-
- gnutls_free(buffer);
+ print_name(str, "\t\t\t", type, &dist);
}
}
static void
-print_key_purpose(gnutls_buffer_st * str, const char *prefix, int type,
- cert_type_t cert)
+print_key_purpose(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
{
int indx;
- char *buffer = NULL;
- size_t size;
+ gnutls_datum_t oid;
+ char *p;
int err;
+ gnutls_x509_key_purposes_t purposes;
+
+ err = gnutls_x509_key_purpose_init(&purposes);
+ if (err < 0) {
+ addf(str, "error: gnutls_x509_key_purpose_init: %s\n",
+ gnutls_strerror(err));
+ return;
+ }
- for (indx = 0;; indx++) {
- size = 0;
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_key_purpose_oid(cert.crt,
- indx,
- buffer,
- &size,
- NULL);
- else if (type == TYPE_CRQ)
- err =
- gnutls_x509_crq_get_key_purpose_oid(cert.crq,
- indx,
- buffer,
- &size,
- NULL);
- else
- return;
+ err = gnutls_x509_ext_import_key_purposes(der, purposes, 0);
+ if (err < 0) {
+ addf(str, "error: gnutls_x509_ext_import_key_purposes: %s\n",
+ gnutls_strerror(err));
+ return;
+ }
+ for (indx = 0;; indx++) {
+ err = gnutls_x509_key_purpose_get(purposes, indx, &oid);
if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
return;
- if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
- addf(str, "error: get_key_purpose_oid: %s\n",
+ else if (err < GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ addf(str, "error: gnutls_x509_key_purpose_get: %s\n",
gnutls_strerror(err));
return;
}
- buffer = gnutls_malloc(size);
- if (!buffer) {
- addf(str, "error: malloc: %s\n",
- gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
- return;
- }
-
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_key_purpose_oid(cert.crt,
- indx,
- buffer,
- &size,
- NULL);
- else
- err =
- gnutls_x509_crq_get_key_purpose_oid(cert.crq,
- indx,
- buffer,
- &size,
- NULL);
-
- if (err < 0) {
- gnutls_free(buffer);
- addf(str, "error: get_key_purpose_oid2: %s\n",
- gnutls_strerror(err));
- return;
- }
-
- if (strcmp(buffer, GNUTLS_KP_TLS_WWW_SERVER) == 0)
+ p = (void*)oid.data;
+ if (strcmp(p, GNUTLS_KP_TLS_WWW_SERVER) == 0)
addf(str, _("%s\t\t\tTLS WWW Server.\n"), prefix);
- else if (strcmp(buffer, GNUTLS_KP_TLS_WWW_CLIENT) == 0)
+ else if (strcmp(p, GNUTLS_KP_TLS_WWW_CLIENT) == 0)
addf(str, _("%s\t\t\tTLS WWW Client.\n"), prefix);
- else if (strcmp(buffer, GNUTLS_KP_CODE_SIGNING) == 0)
+ else if (strcmp(p, GNUTLS_KP_CODE_SIGNING) == 0)
addf(str, _("%s\t\t\tCode signing.\n"), prefix);
- else if (strcmp(buffer, GNUTLS_KP_EMAIL_PROTECTION) == 0)
+ else if (strcmp(p, GNUTLS_KP_EMAIL_PROTECTION) == 0)
addf(str, _("%s\t\t\tEmail protection.\n"),
prefix);
- else if (strcmp(buffer, GNUTLS_KP_TIME_STAMPING) == 0)
+ else if (strcmp(p, GNUTLS_KP_TIME_STAMPING) == 0)
addf(str, _("%s\t\t\tTime stamping.\n"), prefix);
- else if (strcmp(buffer, GNUTLS_KP_OCSP_SIGNING) == 0)
+ else if (strcmp(p, GNUTLS_KP_OCSP_SIGNING) == 0)
addf(str, _("%s\t\t\tOCSP signing.\n"), prefix);
- else if (strcmp(buffer, GNUTLS_KP_IPSEC_IKE) == 0)
+ else if (strcmp(p, GNUTLS_KP_IPSEC_IKE) == 0)
addf(str, _("%s\t\t\tIpsec IKE.\n"), prefix);
- else if (strcmp(buffer, GNUTLS_KP_ANY) == 0)
+ else if (strcmp(p, GNUTLS_KP_ANY) == 0)
addf(str, _("%s\t\t\tAny purpose.\n"), prefix);
else
- addf(str, "%s\t\t\t%s\n", prefix, buffer);
-
- gnutls_free(buffer);
+ addf(str, "%s\t\t\t%s\n", prefix, p);
}
+ gnutls_x509_key_purpose_deinit(purposes);
}
static void
-print_basic(gnutls_buffer_st * str, const char *prefix, int type,
- cert_type_t cert)
+print_basic(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
{
int pathlen;
+ unsigned ca;
int err;
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_basic_constraints(cert.crt, NULL,
- NULL, &pathlen);
- else if (type == TYPE_CRQ)
- err =
- gnutls_x509_crq_get_basic_constraints(cert.crq, NULL,
- NULL, &pathlen);
- else
- return;
-
+ err = gnutls_x509_ext_import_basic_constraints(der, &ca, &pathlen);
if (err < 0) {
addf(str, "error: get_basic_constraints: %s\n",
gnutls_strerror(err));
return;
}
- if (err == 0)
+ if (ca == 0)
addf(str, _("%s\t\t\tCertificate Authority (CA): FALSE\n"),
prefix);
else
@@ -758,187 +581,60 @@ print_basic(gnutls_buffer_st * str, const char *prefix, int type,
static void
-print_altname(gnutls_buffer_st * str, const char *prefix,
- unsigned int altname_type, cert_type_t cert)
+print_altname(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
{
unsigned int altname_idx;
- gnutls_datum_t t;
- char *buffer;
- size_t size;
+ gnutls_subject_alt_names_t names;
+ unsigned int type;
+ gnutls_datum_t san;
+ gnutls_datum_t othername;
int err;
- for (altname_idx = 0;; altname_idx++) {
+ err = gnutls_subject_alt_names_init(&names);
+ if (err < 0) {
+ addf(str, "error: gnutls_subject_alt_names_init: %s\n",
+ gnutls_strerror(err));
+ return;
+ }
- buffer = NULL;
- size = 0;
- if (altname_type == TYPE_CRT_SAN)
- err =
- gnutls_x509_crt_get_subject_alt_name(cert.crt,
- altname_idx,
- buffer,
- &size,
- NULL);
- else if (altname_type == TYPE_CRQ_SAN)
- err =
- gnutls_x509_crq_get_subject_alt_name(cert.crq,
- altname_idx,
- buffer,
- &size,
- NULL,
- NULL);
- else if (altname_type == TYPE_CRT_IAN)
- err =
- gnutls_x509_crt_get_issuer_alt_name(cert.crt,
- altname_idx,
- buffer,
- &size,
- NULL);
- else
- return;
+ err = gnutls_x509_ext_import_subject_alt_names(der, names, 0);
+ if (err < 0) {
+ addf(str, "error: gnutls_x509_ext_import_subject_alt_names: %s\n",
+ gnutls_strerror(err));
+ return;
+ }
+ for (altname_idx = 0;; altname_idx++) {
+ err = gnutls_subject_alt_names_get(names, altname_idx,
+ &type, &san, &othername);
if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
break;
- if (err < 0 && err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ else if (err < 0) {
addf(str,
- "error: get_subject/issuer_alt_name: %s\n",
+ "error: gnutls_subject_alt_names_get: %s\n",
gnutls_strerror(err));
return;
}
- buffer = gnutls_malloc(size);
- if (!buffer) {
- addf(str, "error: malloc: %s\n",
- gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
- return;
- }
-
- if (altname_type == TYPE_CRT_SAN) {
- err =
- gnutls_x509_crt_get_subject_alt_name(cert.crt,
- altname_idx,
- buffer,
- &size,
- NULL);
- } else if (altname_type == TYPE_CRQ_SAN) {
- err =
- gnutls_x509_crq_get_subject_alt_name(cert.crq,
- altname_idx,
- buffer,
- &size,
- NULL,
- NULL);
- } else if (altname_type == TYPE_CRT_IAN) {
- err =
- gnutls_x509_crt_get_issuer_alt_name(cert.crt,
- altname_idx,
- buffer,
- &size,
- NULL);
- }
- if (err < 0) {
- gnutls_free(buffer);
+ if (type == GNUTLS_SAN_OTHERNAME) {
addf(str,
- "error: get_subject/issuer_alt_name2: %s\n",
- gnutls_strerror(err));
- return;
- }
-
- if (err == GNUTLS_SAN_OTHERNAME) {
- char *oid = NULL;
- size_t oidsize;
-
- oidsize = 0;
- if (altname_type == TYPE_CRT_SAN)
- err =
- gnutls_x509_crt_get_subject_alt_othername_oid
- (cert.crt, altname_idx, oid, &oidsize);
- else if (altname_type == TYPE_CRQ_SAN)
- err =
- gnutls_x509_crq_get_subject_alt_othername_oid
- (cert.crq, altname_idx, oid, &oidsize);
- else if (altname_type == TYPE_CRT_IAN)
- err =
- gnutls_x509_crt_get_issuer_alt_othername_oid
- (cert.crt, altname_idx, oid, &oidsize);
-
- if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
- gnutls_free(buffer);
- addf(str,
- "error: get_subject/issuer_alt_othername_oid: %s (%d)\n",
- gnutls_strerror(err), err);
- return;
- }
-
- oid = gnutls_malloc(oidsize);
- if (!oid) {
- gnutls_free(buffer);
- addf(str, "error: malloc: %s\n",
- gnutls_strerror
- (GNUTLS_E_MEMORY_ERROR));
- return;
- }
-
- if (altname_type == TYPE_CRT_SAN)
- err =
- gnutls_x509_crt_get_subject_alt_othername_oid
- (cert.crt, altname_idx, oid, &oidsize);
- else if (altname_type == TYPE_CRQ_SAN)
- err =
- gnutls_x509_crq_get_subject_alt_othername_oid
- (cert.crq, altname_idx, oid, &oidsize);
- else if (altname_type == TYPE_CRT_IAN)
- err =
- gnutls_x509_crt_get_issuer_alt_othername_oid
- (cert.crt, altname_idx, oid, &oidsize);
-
- if (err < 0) {
- gnutls_free(buffer);
- gnutls_free(oid);
- addf(str,
- "error: get_subject_alt_othername_oid2: %s\n",
- gnutls_strerror(err));
- return;
- }
-
- if (err == GNUTLS_SAN_OTHERNAME_XMPP) {
- if (strlen(buffer) != size) {
- adds(str,
- _
- ("warning: altname contains an embedded NUL, "
- "replacing with '!'\n"));
- while (strlen(buffer) < size)
- buffer[strlen(buffer)] =
- '!';
- }
-
- addf(str,
- _("%s\t\t\tXMPP Address: %.*s\n"),
- prefix, (int) size, buffer);
- } else {
- addf(str,
- _("%s\t\t\totherName OID: %.*s\n"),
- prefix, (int) oidsize, oid);
- addf(str, _("%s\t\t\totherName DER: "),
+ _("%s\t\t\totherName OID: %.*s\n"),
+ prefix, (int)othername.size, (char*)othername.data);
+ addf(str, _("%s\t\t\totherName DER: "),
prefix);
- _gnutls_buffer_hexprint(str, buffer, size);
- addf(str, _("\n%s\t\t\totherName ASCII: "),
+ _gnutls_buffer_hexprint(str, san.data, san.size);
+ addf(str, _("\n%s\t\t\totherName ASCII: "),
prefix);
- _gnutls_buffer_asciiprint(str, buffer,
- size);
+ _gnutls_buffer_asciiprint(str, (char*)san.data, san.size);
addf(str, "\n");
- }
- gnutls_free(oid);
} else {
char pfx[16];
- t.data = (void*)buffer;
- t.size = size;
snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
- print_name(str, pfx, err, &t);
+ print_name(str, pfx, type, &san);
}
-
- gnutls_free(buffer);
}
+ gnutls_subject_alt_names_deinit(names);
}
static void
@@ -999,333 +695,308 @@ print_unique_ids(gnutls_buffer_st * str, const gnutls_x509_crt_t cert)
}
}
-static void
-print_extensions(gnutls_buffer_st * str, const char *prefix, int type,
- cert_type_t cert)
+struct ext_indexes_st {
+ int san;
+ int ian;
+ int proxy;
+ int basic;
+ int keyusage;
+ int keypurpose;
+ int ski;
+ int aki, nc;
+ int crldist, pkey_usage_period;
+};
+
+static void print_extension(gnutls_buffer_st * str, const char *prefix,
+ struct ext_indexes_st *idx, const char *oid,
+ unsigned critical, gnutls_datum_t *der)
{
- unsigned i, j;
int err;
- int san_idx = 0;
- int ian_idx = 0;
- int proxy_idx = 0;
- int basic_idx = 0;
- int keyusage_idx = 0;
- int keypurpose_idx = 0;
- int ski_idx = 0;
- int aki_idx = 0, nc_idx = 0;
- int crldist_idx = 0, pkey_usage_period_idx = 0;
- gnutls_datum_t der = {NULL, 0};
+ unsigned j;
char pfx[16];
- for (i = 0;; i++) {
- char oid[MAX_OID_SIZE] = "";
- size_t sizeof_oid = sizeof(oid);
- unsigned int critical;
+ if (strcmp(oid, "2.5.29.19") == 0) {
+ if (idx->basic) {
+ addf(str,
+ "error: more than one basic constraint\n");
+ }
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_extension_info(cert.crt, i,
- oid,
- &sizeof_oid,
- &critical);
+ addf(str, _("%s\t\tBasic Constraints (%s):\n"),
+ prefix,
+ critical ? _("critical") : _("not critical"));
- else if (type == TYPE_CRQ)
- err =
- gnutls_x509_crq_get_extension_info(cert.crq, i,
- oid,
- &sizeof_oid,
- &critical);
- else {
- gnutls_assert();
+ print_basic(str, prefix, der);
+ idx->basic++;
+
+ } else if (strcmp(oid, "2.5.29.14") == 0) {
+ if (idx->ski) {
+ addf(str,
+ "error: more than one SKI extension\n");
+ }
+
+ addf(str,
+ _("%s\t\tSubject Key Identifier (%s):\n"),
+ prefix,
+ critical ? _("critical") : _("not critical"));
+
+ print_ski(str, der);
+
+ idx->ski++;
+ } else if (strcmp(oid, "2.5.29.32") == 0) {
+ struct gnutls_x509_policy_st policy;
+ gnutls_x509_policies_t policies;
+ const char *name;
+ int x;
+
+ err = gnutls_x509_policies_init(&policies);
+ if (err < 0) {
+ addf(str,
+ "error: certificate policies: %s\n",
+ gnutls_strerror(err));
return;
}
+ err = gnutls_x509_ext_import_policies(der, policies, 0);
if (err < 0) {
- if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
- break;
- addf(str, "error: get_extension_info: %s\n",
+ addf(str,
+ "error: certificate policies import: %s\n",
gnutls_strerror(err));
- continue;
+ return;
}
- if (i == 0)
- addf(str, _("%s\tExtensions:\n"), prefix);
+ for (x = 0;; x++) {
+ err = gnutls_x509_policies_get(policies, x, &policy);
+ if (err ==
+ GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+ break;
- if (strcmp(oid, "2.5.29.19") == 0) {
- if (basic_idx) {
+ if (err < 0) {
addf(str,
- "error: more than one basic constraint\n");
- continue;
+ "error: certificate policy: %s\n",
+ gnutls_strerror(err));
+ break;
}
- addf(str, _("%s\t\tBasic Constraints (%s):\n"),
- prefix,
- critical ? _("critical") : _("not critical"));
-
- print_basic(str, prefix, type, cert);
-
- basic_idx++;
- } else if (strcmp(oid, "2.5.29.14") == 0) {
- if (ski_idx) {
+ if (x == 0)
addf(str,
- "error: more than one SKI extension\n");
- continue;
+ "%s\t\tCertificate Policies (%s):\n",
+ prefix,
+ critical ? _("critical") :
+ _("not critical"));
+
+ addf(str, "%s\t\t\t%s\n", prefix, policy.oid);
+ for (j = 0; j < policy.qualifiers; j++) {
+ if (policy.qualifier[j].type ==
+ GNUTLS_X509_QUALIFIER_URI)
+ name = "URI";
+ else if (policy.qualifier[j].
+ type ==
+ GNUTLS_X509_QUALIFIER_NOTICE)
+ name = "Note";
+ else
+ name = "Unknown qualifier";
+ addf(str, "%s\t\t\t\t%s: %s\n",
+ prefix, name,
+ policy.qualifier[j].data);
}
+ gnutls_x509_policy_release(&policy);
+ }
+ gnutls_x509_policies_deinit(policies);
+ } else if (strcmp(oid, "2.5.29.35") == 0) {
+ if (idx->aki) {
addf(str,
- _("%s\t\tSubject Key Identifier (%s):\n"),
- prefix,
- critical ? _("critical") : _("not critical"));
-
- if (type == TYPE_CRT)
- print_ski(str, cert.crt);
-
- ski_idx++;
- } else if (strcmp(oid, "2.5.29.32") == 0) {
- struct gnutls_x509_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;
- }
-
- if (x == 0)
- addf(str,
- "%s\t\tCertificate Policies (%s):\n",
- prefix,
- critical ? _("critical") :
- _("not critical"));
-
- addf(str, "%s\t\t\t%s\n", prefix,
- policy.oid);
- for (j = 0; j < policy.qualifiers; j++) {
- if (policy.qualifier[j].type ==
- GNUTLS_X509_QUALIFIER_URI)
- name = "URI";
- else if (policy.qualifier[j].
- type ==
- GNUTLS_X509_QUALIFIER_NOTICE)
- name = "Note";
- else
- name = "Unknown qualifier";
- addf(str, "%s\t\t\t\t%s: %s\n",
- prefix, name,
- policy.qualifier[j].data);
- }
+ "error: more than one AKI extension\n");
+ }
- gnutls_x509_policy_release(&policy);
- }
- } else if (strcmp(oid, "2.5.29.35") == 0) {
+ addf(str,
+ _("%s\t\tAuthority Key Identifier (%s):\n"),
+ prefix,
+ critical ? _("critical") : _("not critical"));
- if (aki_idx) {
- addf(str,
- "error: more than one AKI extension\n");
- continue;
- }
+ print_aki(str, der);
+ idx->aki++;
+ } else if (strcmp(oid, "2.5.29.15") == 0) {
+ if (idx->keyusage) {
addf(str,
- _("%s\t\tAuthority Key Identifier (%s):\n"),
- prefix,
- critical ? _("critical") : _("not critical"));
-
- if (type == TYPE_CRT)
- print_aki(str, TYPE_CRT, cert);
-
- aki_idx++;
- } else if (strcmp(oid, "2.5.29.15") == 0) {
- if (keyusage_idx) {
- addf(str,
- "error: more than one key usage extension\n");
- continue;
- }
+ "error: more than one key usage extension\n");
+ }
- addf(str, _("%s\t\tKey Usage (%s):\n"), prefix,
+ addf(str, _("%s\t\tKey Usage (%s):\n"), prefix,
critical ? _("critical") : _("not critical"));
- snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
- print_key_usage(str, pfx, type, cert);
-
- keyusage_idx++;
- } else if (strcmp(oid, "2.5.29.16") == 0) {
- if (pkey_usage_period_idx) {
- addf(str,
- "error: more than one private key usage period extension\n");
- continue;
- }
+ snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
+ print_key_usage(str, pfx, der);
+ idx->keyusage++;
+ } else if (strcmp(oid, "2.5.29.16") == 0) {
+ if (idx->pkey_usage_period) {
addf(str,
- _("%s\t\tPrivate Key Usage Period (%s):\n"),
- prefix,
- critical ? _("critical") : _("not critical"));
-
- print_private_key_usage_period(str, prefix, type,
- cert);
-
- pkey_usage_period_idx++;
- } else if (strcmp(oid, "2.5.29.37") == 0) {
- if (keypurpose_idx) {
- addf(str,
- "error: more than one key purpose extension\n");
- continue;
- }
+ "error: more than one private key usage period extension\n");
+ }
- addf(str, _("%s\t\tKey Purpose (%s):\n"), prefix,
- critical ? _("critical") : _("not critical"));
+ addf(str,
+ _("%s\t\tPrivate Key Usage Period (%s):\n"),
+ prefix,
+ critical ? _("critical") : _("not critical"));
- print_key_purpose(str, prefix, type, cert);
- keypurpose_idx++;
- } else if (strcmp(oid, "2.5.29.17") == 0) {
- if (san_idx) {
- addf(str,
- "error: more than one SKI extension\n");
- continue;
- }
+ print_private_key_usage_period(str, prefix, der);
+ idx->pkey_usage_period++;
+ } else if (strcmp(oid, "2.5.29.37") == 0) {
+ if (idx->keypurpose) {
addf(str,
- _("%s\t\tSubject Alternative Name (%s):\n"),
- prefix,
- critical ? _("critical") : _("not critical"));
+ "error: more than one key purpose extension\n");
+ }
- print_altname(str, prefix, type, cert);
+ addf(str, _("%s\t\tKey Purpose (%s):\n"), prefix,
+ critical ? _("critical") : _("not critical"));
- san_idx++;
- } else if (strcmp(oid, "2.5.29.18") == 0) {
- if (ian_idx) {
- addf(str,
- "error: more than one Issuer AltName extension\n");
- continue;
- }
+ print_key_purpose(str, prefix, der);
+ idx->keypurpose++;
+ } else if (strcmp(oid, "2.5.29.17") == 0) {
+ if (idx->san) {
+ addf(str,
+ "error: more than one SKI extension\n");
+ }
+ addf(str,
+ _("%s\t\tSubject Alternative Name (%s):\n"),
+ prefix,
+ critical ? _("critical") : _("not critical"));
+ print_altname(str, prefix, der);
+ idx->san++;
+ } else if (strcmp(oid, "2.5.29.18") == 0) {
+ if (idx->ian) {
addf(str,
- _("%s\t\tIssuer Alternative Name (%s):\n"),
- prefix,
- critical ? _("critical") : _("not critical"));
+ "error: more than one Issuer AltName extension\n");
+ }
- print_altname(str, prefix, TYPE_CRT_IAN, cert);
+ addf(str,
+ _("%s\t\tIssuer Alternative Name (%s):\n"),
+ prefix,
+ critical ? _("critical") : _("not critical"));
- ian_idx++;
- } else if (strcmp(oid, "2.5.29.31") == 0) {
- if (crldist_idx) {
- addf(str,
- "error: more than one CRL distribution point\n");
- continue;
- }
+ print_altname(str, prefix, der);
+ idx->ian++;
+ } else if (strcmp(oid, "2.5.29.31") == 0) {
+ if (idx->crldist) {
addf(str,
- _("%s\t\tCRL Distribution points (%s):\n"),
- prefix,
- critical ? _("critical") : _("not critical"));
+ "error: more than one CRL distribution point\n");
+ }
- if (type == TYPE_CRT)
- print_crldist(str, cert.crt);
- crldist_idx++;
- } else if (strcmp(oid, "1.3.6.1.5.5.7.1.14") == 0) {
- if (proxy_idx) {
- addf(str,
- "error: more than one proxy extension\n");
- continue;
- }
+ addf(str,
+ _("%s\t\tCRL Distribution points (%s):\n"),
+ prefix,
+ critical ? _("critical") : _("not critical"));
+ print_crldist(str, der);
+ idx->crldist++;
+ } else if (strcmp(oid, "1.3.6.1.5.5.7.1.14") == 0) {
+ if (idx->proxy) {
addf(str,
+ "error: more than one proxy extension\n");
+ }
+
+ addf(str,
_
- ("%s\t\tProxy Certificate Information (%s):\n"),
- prefix,
- critical ? _("critical") : _("not critical"));
+ ("%s\t\tProxy Certificate Information (%s):\n"),
+ prefix,
+ critical ? _("critical") : _("not critical"));
- if (type == TYPE_CRT)
- print_proxy(str, cert.crt);
+ print_proxy(str, der);
- proxy_idx++;
- } else if (strcmp(oid, "1.3.6.1.5.5.7.1.1") == 0) {
- addf(str, _("%s\t\tAuthority Information "
- "Access (%s):\n"), prefix,
- critical ? _("critical") : _("not critical"));
+ idx->proxy++;
+ } else if (strcmp(oid, "1.3.6.1.5.5.7.1.1") == 0) {
+ addf(str, _("%s\t\tAuthority Information "
+ "Access (%s):\n"), prefix,
+ critical ? _("critical") : _("not critical"));
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_extension_data2
- (cert.crt, i, &der);
- else if (type == TYPE_CRQ)
- err =
- gnutls_x509_crq_get_extension_data2
- (cert.crq, i, &der);
- else {
- gnutls_assert();
- return;
- }
+ print_aia(str, der);
+ } else if (strcmp(oid, "2.5.29.30") == 0) {
+ if (idx->nc) {
+ addf(str,
+ "error: more than one name constraints extension\n");
+ }
+ idx->nc++;
- if (err < 0) {
- addf(str,
- "error: get_extension_data2: %s\n",
- gnutls_strerror(err));
- continue;
- }
+ addf(str, _("%s\t\tName Constraints (%s):\n"), prefix,
+ critical ? _("critical") : _("not critical"));
- print_aia(str, &der);
+ print_nc(str, prefix, der);
+ } else {
+ addf(str, _("%s\t\tUnknown extension %s (%s):\n"),
+ prefix, oid,
+ critical ? _("critical") : _("not critical"));
- _gnutls_free_datum(&der);
- } else if (strcmp(oid, "2.5.29.30") == 0) {
- if (nc_idx) {
- addf(str,
- "error: more than one name constraints extension\n");
- continue;
- }
- nc_idx++;
+ addf(str, _("%s\t\t\tASCII: "), prefix);
+ _gnutls_buffer_asciiprint(str, (char*)der->data, der->size);
- addf(str, _("%s\t\tName Constraints (%s):\n"), prefix,
- critical ? _("critical") : _("not critical"));
+ addf(str, "\n");
+ addf(str, _("%s\t\t\tHexdump: "), prefix);
+ _gnutls_buffer_hexprint(str, (char*)der->data, der->size);
+ adds(str, "\n");
+ }
+}
- if (type == TYPE_CRT)
- print_nc(str, prefix, cert.crt);
- } else {
+static void
+print_extensions(gnutls_buffer_st * str, const char *prefix, int type,
+ cert_type_t cert)
+{
+ unsigned i;
+ int err;
+ gnutls_datum_t der = {NULL, 0};
+ struct ext_indexes_st idx;
- addf(str, _("%s\t\tUnknown extension %s (%s):\n"),
- prefix, oid,
- critical ? _("critical") : _("not critical"));
+ memset(&idx, 0, sizeof(idx));
- if (type == TYPE_CRT)
- err =
- gnutls_x509_crt_get_extension_data2
- (cert.crt, i, &der);
- else if (type == TYPE_CRQ)
- err =
- gnutls_x509_crq_get_extension_data2
- (cert.crq, i, &der);
- else {
- gnutls_assert();
- return;
- }
+ for (i = 0;; i++) {
+ char oid[MAX_OID_SIZE] = "";
+ size_t sizeof_oid = sizeof(oid);
+ unsigned int critical;
- if (err < 0) {
- addf(str,
- "error: get_extension_data2: %s\n",
- gnutls_strerror(err));
- continue;
- }
+ if (type == TYPE_CRT)
+ err =
+ gnutls_x509_crt_get_extension_info(cert.crt, i,
+ oid,
+ &sizeof_oid,
+ &critical);
- addf(str, _("%s\t\t\tASCII: "), prefix);
- _gnutls_buffer_asciiprint(str, (char*)der.data, der.size);
- addf(str, "\n");
+ else if (type == TYPE_CRQ)
+ err =
+ gnutls_x509_crq_get_extension_info(cert.crq, i,
+ oid,
+ &sizeof_oid,
+ &critical);
+ else {
+ gnutls_assert();
+ return;
+ }
- addf(str, _("%s\t\t\tHexdump: "), prefix);
- _gnutls_buffer_hexprint(str, (char*)der.data, der.size);
- adds(str, "\n");
+ if (err < 0) {
+ if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+ break;
+ addf(str, "error: get_extension_info: %s\n",
+ gnutls_strerror(err));
+ continue;
+ }
+
+ if (i == 0)
+ addf(str, _("%s\tExtensions:\n"), prefix);
- _gnutls_free_datum(&der);
+ if (type == TYPE_CRT)
+ err = gnutls_x509_crt_get_extension_data2(cert.crt, i, &der);
+ else
+ err = gnutls_x509_crq_get_extension_data2(cert.crq, i, &der);
+
+ if (err < 0) {
+ der.data = NULL;
+ der.size = 0;
}
+
+ print_extension(str, prefix, &idx, oid, critical, &der);
}
}
@@ -1997,7 +1668,7 @@ static void print_oneline(gnutls_buffer_st * str, gnutls_x509_crt_t cert)
* gnutls_x509_crt_print:
* @cert: The structure to be printed
* @format: Indicate the format to use
- * @out: Newly allocated datum with (0) terminated string.
+ * @out: Newly allocated datum with zero terminated string.
*
* This function will pretty print a X.509 certificate, suitable for
* display to a human.
@@ -2222,7 +1893,7 @@ print_crl(gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
crl_nr++;
} else if (strcmp(oid, "2.5.29.35") == 0) {
- cert_type_t ccert;
+ gnutls_datum_t der;
if (aki_idx) {
addf(str,
@@ -2236,13 +1907,19 @@ print_crl(gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
critical ? _("critical") :
_("not critical"));
- ccert.crl = crl;
- print_aki(str, TYPE_CRL, ccert);
+ err = gnutls_x509_crl_get_extension_data2(crl, i, &der);
+ if (err < 0) {
+ addf(str,
+ "error: get_extension_data2: %s\n",
+ gnutls_strerror(err));
+ continue;
+ }
+ print_aki(str, &der);
+ gnutls_free(der.data);
aki_idx++;
} else {
- char *buffer;
- size_t extlen = 0;
+ gnutls_datum_t der;
addf(str,
_("\t\tUnknown extension %s (%s):\n"),
@@ -2251,32 +1928,10 @@ print_crl(gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
_("not critical"));
err =
- gnutls_x509_crl_get_extension_data(crl,
- i,
- NULL,
- &extlen);
- if (err < 0) {
- addf(str,
- "error: get_extension_data: %s\n",
- gnutls_strerror(err));
- continue;
- }
-
- buffer = gnutls_malloc(extlen);
- if (!buffer) {
- addf(str, "error: malloc: %s\n",
- gnutls_strerror
- (GNUTLS_E_MEMORY_ERROR));
- continue;
- }
-
- err =
- gnutls_x509_crl_get_extension_data(crl,
+ gnutls_x509_crl_get_extension_data2(crl,
i,
- buffer,
- &extlen);
+ &der);
if (err < 0) {
- gnutls_free(buffer);
addf(str,
"error: get_extension_data2: %s\n",
gnutls_strerror(err));
@@ -2284,16 +1939,14 @@ print_crl(gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
}
adds(str, _("\t\t\tASCII: "));
- _gnutls_buffer_asciiprint(str, buffer,
- extlen);
+ _gnutls_buffer_asciiprint(str, (char*)der.data, der.size);
adds(str, "\n");
adds(str, _("\t\t\tHexdump: "));
- _gnutls_buffer_hexprint(str, buffer,
- extlen);
+ _gnutls_buffer_hexprint(str, der.data, der.size);
adds(str, "\n");
- gnutls_free(buffer);
+ gnutls_free(der.data);
}
}
}
@@ -2410,7 +2063,7 @@ print_crl(gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
* gnutls_x509_crl_print:
* @crl: The structure to be printed
* @format: Indicate the format to use
- * @out: Newly allocated datum with (0) terminated string.
+ * @out: Newly allocated datum with zero terminated string.
*
* This function will pretty print a X.509 certificate revocation
* list, suitable for display to a human.
@@ -2706,7 +2359,7 @@ static void print_crq_other(gnutls_buffer_st * str, gnutls_x509_crq_t crq)
* gnutls_x509_crq_print:
* @crq: The structure to be printed
* @format: Indicate the format to use
- * @out: Newly allocated datum with (0) terminated string.
+ * @out: Newly allocated datum with zero terminated string.
*
* This function will pretty print a certificate request, suitable for
* display to a human.
@@ -2754,9 +2407,6 @@ print_pubkey_other(gnutls_buffer_st * str, gnutls_pubkey_t pubkey,
size_t size = sizeof(buffer);
int ret;
unsigned int usage;
- cert_type_t ccert;
-
- ccert.pubkey = pubkey;
ret = gnutls_pubkey_get_key_usage(pubkey, &usage);
if (ret < 0) {
@@ -2767,7 +2417,7 @@ print_pubkey_other(gnutls_buffer_st * str, gnutls_pubkey_t pubkey,
adds(str, "\n");
adds(str, _("Public Key Usage:\n"));
- print_key_usage(str, "\t", TYPE_PUBKEY, ccert);
+ print_key_usage2(str, "\t", pubkey->key_usage);
ret = gnutls_pubkey_get_key_id(pubkey, 0, buffer, &size);
if (ret < 0) {
@@ -2785,7 +2435,7 @@ print_pubkey_other(gnutls_buffer_st * str, gnutls_pubkey_t pubkey,
* gnutls_pubkey_print:
* @pubkey: The structure to be printed
* @format: Indicate the format to use
- * @out: Newly allocated datum with (0) terminated string.
+ * @out: Newly allocated datum with zero terminated string.
*
* This function will pretty print public key information, suitable for
* display to a human.
@@ -2823,3 +2473,42 @@ gnutls_pubkey_print(gnutls_pubkey_t pubkey,
return ret;
}
+
+/**
+ * gnutls_x509_ext_print:
+ * @exts: The structures to be printed
+ * @exts_size: the number of available structures
+ * @format: Indicate the format to use
+ * @out: Newly allocated datum with zero terminated string.
+ *
+ * This function will pretty print X.509 certificate extensions,
+ * suitable for display to a human.
+ *
+ * The output @out needs to be deallocated using gnutls_free().
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_ext_print(gnutls_x509_ext_st *exts, unsigned int exts_size,
+ gnutls_certificate_print_formats_t format,
+ gnutls_datum_t * out)
+{
+ gnutls_buffer_st str;
+ struct ext_indexes_st idx;
+ int ret;
+ unsigned i;
+
+ memset(&idx, 0, sizeof(idx));
+ _gnutls_buffer_init(&str);
+
+ for (i=0;i<exts_size;i++)
+ print_extension(&str, "\t", &idx, (char*)exts[i].oid, exts[i].critical, &exts[i].data);
+
+ _gnutls_buffer_append_data(&str, "\x00", 1);
+
+ ret = _gnutls_buffer_to_datum(&str, out);
+ if (out->size > 0)
+ out->size--;
+ return ret;
+}
diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c
index afbc6e9951..5aeceefc9e 100644
--- a/lib/x509/x509_ext.c
+++ b/lib/x509/x509_ext.c
@@ -702,7 +702,7 @@ void gnutls_x509_aki_deinit(gnutls_x509_aki_t aki)
* @id: Will hold the identifier
*
* This function will return the key identifier as stored in
- * the @aki structure.
+ * the @aki structure. The identifier should be treated as constant.
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
* if the index is out of bounds, otherwise a negative error value.
@@ -1400,6 +1400,7 @@ int gnutls_x509_ext_export_basic_constraints(unsigned int ca, int pathlen,
*
* This function will return the information from a proxy certificate
* extension. It reads the ProxyCertInfo X.509 extension (1.3.6.1.5.5.7.1.14).
+ * The @policyLanguage and @policy values must be deinitialized using gnutls_free() after use.
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value.
@@ -1467,6 +1468,7 @@ int gnutls_x509_ext_import_proxy(const gnutls_datum_t * ext, int *pathlen,
} else {
if (policy) {
*policy = (char *)value.data;
+ value.data = NULL;
}
if (sizeof_policy)
*sizeof_policy = value.size;
@@ -3034,3 +3036,86 @@ int gnutls_x509_ext_export_key_purposes(gnutls_x509_key_purposes_t p,
asn1_delete_structure(&c2);
return ret;
}
+
+/**
+ * gnutls_ext_deinit:
+ * @ext: The extensions structure
+ *
+ * This function will deinitialize an extensions structure.
+ *
+ * Since: 3.3.8
+ **/
+void gnutls_x509_ext_deinit(gnutls_x509_ext_st *ext)
+{
+ gnutls_free(ext->oid);
+ gnutls_free(ext->data.data);
+}
+
+int _gnutls_x509_decode_ext(const gnutls_datum_t *der, gnutls_x509_ext_st *out)
+{
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+ char str_critical[10];
+ char oid[MAX_OID_SIZE];
+ int result, len, ret;
+
+ memset(out, 0, sizeof(*out));
+
+ /* decode der */
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.Extension", &c2);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ result = asn1_der_decoding(&c2, der->data, der->size, NULL);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ ret = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ len = sizeof(oid)-1;
+ result = asn1_read_value(c2, "extnID", oid, &len);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ ret = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ len = sizeof(str_critical)-1;
+ result = asn1_read_value(c2, "critical", str_critical, &len);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ ret = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if (str_critical[0] == 'T')
+ out->critical = 1;
+ else
+ out->critical = 0;
+
+ ret = _gnutls_x509_read_value(c2, "extnValue", &out->data);
+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE || ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
+ out->data.data = NULL;
+ out->data.size = 0;
+ } else if (ret < 0) {
+ gnutls_assert();
+ goto fail;
+ }
+
+ out->oid = gnutls_strdup(oid);
+ if (out->oid == NULL) {
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto fail;
+ }
+
+ ret = 0;
+ goto cleanup;
+ fail:
+ memset(out, 0, sizeof(*out));
+ cleanup:
+ asn1_delete_structure(&c2);
+ return ret;
+
+}