diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-07-20 11:27:35 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-07-20 11:32:32 +0200 |
commit | 6c9dadf6c2e2e158e1db42d89816162d1f50da62 (patch) | |
tree | 5779b74ddb78e4e1d768741b0b9a62b8af814d13 /lib/x509/x509_dn.c | |
parent | 24e98b1aa9e52cda9c13b1d24b42e3b2ed8e4473 (diff) | |
download | gnutls-6c9dadf6c2e2e158e1db42d89816162d1f50da62.tar.gz |
Moved the gnutls_x509_dn API functions to x509_dn.cdn-encoding
Diffstat (limited to 'lib/x509/x509_dn.c')
-rw-r--r-- | lib/x509/x509_dn.c | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/lib/x509/x509_dn.c b/lib/x509/x509_dn.c index 59bc3c6187..c3737dd307 100644 --- a/lib/x509/x509_dn.c +++ b/lib/x509/x509_dn.c @@ -302,3 +302,294 @@ gnutls_x509_dn_set_str(gnutls_x509_dn_t dn, const char *str, const char **err) return crt_set_dn((set_dn_func) set_dn_by_oid, dn, str, err); } + +/** + * gnutls_x509_dn_init: + * @dn: the object to be initialized + * + * This function initializes a #gnutls_x509_dn_t type. + * + * The object returned must be deallocated using + * gnutls_x509_dn_deinit(). + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 2.4.0 + **/ +int gnutls_x509_dn_init(gnutls_x509_dn_t * dn) +{ + int result; + + *dn = gnutls_calloc(1, sizeof(gnutls_x509_dn_st)); + + if ((result = + asn1_create_element(_gnutls_get_pkix(), + "PKIX1.Name", &(*dn)->asn)) != ASN1_SUCCESS) { + gnutls_assert(); + gnutls_free(*dn); + return _gnutls_asn2err(result); + } + + return 0; +} + +/** + * gnutls_x509_dn_import: + * @dn: the structure that will hold the imported DN + * @data: should contain a DER encoded RDN sequence + * + * This function parses an RDN sequence and stores the result to a + * #gnutls_x509_dn_t type. The data must have been initialized + * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to + * decode the DN. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 2.4.0 + **/ +int gnutls_x509_dn_import(gnutls_x509_dn_t dn, const gnutls_datum_t * data) +{ + int result; + char err[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + + if (data->data == NULL || data->size == 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + result = _asn1_strict_der_decode(&dn->asn, + data->data, data->size, err); + if (result != ASN1_SUCCESS) { + /* couldn't decode DER */ + _gnutls_debug_log("ASN.1 Decoding error: %s\n", err); + gnutls_assert(); + return _gnutls_asn2err(result); + } + + return 0; +} + +/** + * gnutls_x509_dn_deinit: + * @dn: a DN uint8_t object pointer. + * + * This function deallocates the DN object as returned by + * gnutls_x509_dn_import(). + * + * Since: 2.4.0 + **/ +void gnutls_x509_dn_deinit(gnutls_x509_dn_t dn) +{ + asn1_delete_structure(&dn->asn); + gnutls_free(dn); +} + +/** + * gnutls_x509_dn_export: + * @dn: Holds the uint8_t DN object + * @format: the format of output params. One of PEM or DER. + * @output_data: will contain a DN PEM or DER encoded + * @output_data_size: holds the size of output_data (and will be + * replaced by the actual size of parameters) + * + * This function will export the DN to DER or PEM format. + * + * If the buffer provided is not long enough to hold the output, then + * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER + * will be returned. + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN NAME". + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + **/ +int +gnutls_x509_dn_export(gnutls_x509_dn_t dn, + gnutls_x509_crt_fmt_t format, void *output_data, + size_t * output_data_size) +{ + if (dn == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_export_int_named(dn->asn, "rdnSequence", + format, "NAME", + output_data, + output_data_size); +} + +/** + * gnutls_x509_dn_export2: + * @dn: Holds the uint8_t DN object + * @format: the format of output params. One of PEM or DER. + * @out: will contain a DN PEM or DER encoded + * + * This function will export the DN to DER or PEM format. + * + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN NAME". + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 3.1.3 + **/ +int +gnutls_x509_dn_export2(gnutls_x509_dn_t dn, + gnutls_x509_crt_fmt_t format, gnutls_datum_t * out) +{ + if (dn == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_export_int_named2(dn->asn, "rdnSequence", + format, "NAME", out); +} + +/** + * gnutls_x509_dn_get_rdn_ava: + * @dn: a pointer to DN + * @irdn: index of RDN + * @iava: index of AVA. + * @ava: Pointer to structure which will hold output information. + * + * Get pointers to data within the DN. The format of the @ava structure + * is shown below. + * + * struct gnutls_x509_ava_st { + * gnutls_datum_t oid; + * gnutls_datum_t value; + * unsigned long value_tag; + * }; + * + * The X.509 distinguished name is a sequence of sequences of strings + * and this is what the @irdn and @iava indexes model. + * + * Note that @ava will contain pointers into the @dn structure which + * in turns points to the original certificate. Thus you should not + * modify any data or deallocate any of those. + * + * This is a low-level function that requires the caller to do the + * value conversions when necessary (e.g. from UCS-2). + * + * Returns: Returns 0 on success, or an error code. + **/ +int +gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn, + int irdn, int iava, gnutls_x509_ava_st * ava) +{ + ASN1_TYPE rdn, elem; + ASN1_DATA_NODE vnode; + long len; + int lenlen, remlen, ret; + char rbuf[ASN1_MAX_NAME_SIZE]; + unsigned char cls; + const unsigned char *ptr; + + iava++; + irdn++; /* 0->1, 1->2 etc */ + + snprintf(rbuf, sizeof(rbuf), "rdnSequence.?%d.?%d", irdn, iava); + rdn = asn1_find_node(dn->asn, rbuf); + if (!rdn) { + gnutls_assert(); + return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; + } + + snprintf(rbuf, sizeof(rbuf), "?%d.type", iava); + elem = asn1_find_node(rdn, rbuf); + if (!elem) { + gnutls_assert(); + return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; + } + + ret = asn1_read_node_value(elem, &vnode); + if (ret != ASN1_SUCCESS) { + gnutls_assert(); + return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; + } + + ava->oid.data = (void *) vnode.value; + ava->oid.size = vnode.value_len; + + snprintf(rbuf, sizeof(rbuf), "?%d.value", iava); + elem = asn1_find_node(rdn, rbuf); + if (!elem) { + gnutls_assert(); + return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; + } + + ret = asn1_read_node_value(elem, &vnode); + if (ret != ASN1_SUCCESS) { + gnutls_assert(); + return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; + } + /* The value still has the previous tag's length bytes, plus the + * current value's tag and length bytes. Decode them. + */ + + ptr = vnode.value; + remlen = vnode.value_len; + len = asn1_get_length_der(ptr, remlen, &lenlen); + if (len < 0) { + gnutls_assert(); + return GNUTLS_E_ASN1_DER_ERROR; + } + + ptr += lenlen; + remlen -= lenlen; + ret = + asn1_get_tag_der(ptr, remlen, &cls, &lenlen, &ava->value_tag); + if (ret) { + gnutls_assert(); + return _gnutls_asn2err(ret); + } + + ptr += lenlen; + remlen -= lenlen; + + { + signed long tmp; + + tmp = asn1_get_length_der(ptr, remlen, &lenlen); + if (tmp < 0) { + gnutls_assert(); + return GNUTLS_E_ASN1_DER_ERROR; + } + ava->value.size = tmp; + } + ava->value.data = (void *) (ptr + lenlen); + + return 0; +} + +/** + * gnutls_x509_dn_get_str: + * @dn: a pointer to DN + * @str: a datum that will hold the name + * + * This function will allocate buffer and copy the name in the provided DN. + * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as + * described in RFC4514. The output string will be ASCII or UTF-8 + * encoded, depending on the certificate data. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 3.4.2 + **/ +int +gnutls_x509_dn_get_str(gnutls_x509_dn_t dn, gnutls_datum_t *str) +{ + if (dn == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str); +} |