diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-09-10 16:02:12 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-09-15 14:04:27 +0200 |
commit | 65b9475e5d1165a0c9f5351663032989ffa1df9d (patch) | |
tree | 18d447d9ad2f3f6006798941e200361f57d7a324 | |
parent | c21bea788fccc1e72e73579cbb989239c2e62ac1 (diff) | |
download | gnutls-65b9475e5d1165a0c9f5351663032989ffa1df9d.tar.gz |
allow retrieving extensions in a trust module using GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT
Conflicts:
lib/pkcs11.c
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/pkcs11.h | 12 | ||||
-rw-r--r-- | lib/includes/gnutls/x509.h | 13 | ||||
-rw-r--r-- | lib/libgnutls.map | 3 | ||||
-rw-r--r-- | lib/pkcs11.c | 87 | ||||
-rw-r--r-- | lib/pkcs11_int.c | 41 | ||||
-rw-r--r-- | lib/pkcs11_int.h | 9 | ||||
-rw-r--r-- | lib/x509/common.h | 1 | ||||
-rw-r--r-- | lib/x509/output.c | 1217 | ||||
-rw-r--r-- | lib/x509/x509_ext.c | 87 |
10 files changed, 654 insertions, 818 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 21ac4a62b1..9bb16baf82 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 4d586abc86..aacf89a220 100644 --- a/lib/includes/gnutls/x509.h +++ b/lib/includes/gnutls/x509.h @@ -1335,6 +1335,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 256b2fc9a3..cedad180ac 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1020,6 +1020,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 86ca21c1c1..2255575df3 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -44,8 +44,6 @@ #define MAX_PROVIDERS 16 -/* XXX: try to eliminate this */ -#define MAX_CERT_SIZE 32*1024 #define MAX_SLOTS 48 extern void *_gnutls_pkcs11_mutex; @@ -1213,6 +1211,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; @@ -1519,8 +1520,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; @@ -1587,7 +1587,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); @@ -1605,24 +1604,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) { @@ -1649,7 +1635,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; } @@ -2594,7 +2580,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; @@ -2609,7 +2594,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; @@ -3110,6 +3094,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"; @@ -3127,10 +3113,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; @@ -3151,14 +3137,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) @@ -3245,28 +3223,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, @@ -3326,7 +3313,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 3aaa2fe6b4..1595e60061 100644 --- a/lib/x509/output.c +++ b/lib/x509/output.c @@ -95,7 +95,7 @@ char *sname = (char*)name->data; char str_ip[64]; const char *p; - 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, @@ -128,6 +128,10 @@ const char *p; 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); @@ -135,7 +139,7 @@ const char *p; } } -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; @@ -143,8 +147,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)); @@ -168,14 +171,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]; @@ -184,7 +189,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; @@ -263,229 +268,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) @@ -507,8 +380,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; @@ -516,21 +404,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)); @@ -559,166 +433,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 @@ -732,187 +555,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 @@ -973,333 +669,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); } } @@ -1971,7 +1642,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. @@ -2196,7 +1867,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, @@ -2210,13 +1881,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"), @@ -2225,32 +1902,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)); @@ -2258,16 +1913,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); } } } @@ -2384,7 +2037,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. @@ -2680,7 +2333,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. @@ -2728,9 +2381,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) { @@ -2741,7 +2391,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) { @@ -2759,7 +2409,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. @@ -2797,3 +2447,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; + +} |