2 * Copyright (C) 2003-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
25 #include <gnutls_datum.h>
26 #include <gnutls_global.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_str.h>
30 #include <gnutls_num.h>
32 /* This file includes all the required to parse an X.509 Distriguished
33 * Name (you need a parser just to read a name in the X.509 protoocols!!!)
36 /* Escapes a string following the rules from RFC4514.
39 str_escape (const gnutls_datum_t
* str
, gnutls_datum_t
* escaped
)
42 uint8_t *buffer
= NULL
;
46 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
48 /* the string will be at most twice the original */
49 buffer
= gnutls_malloc(str
->size
*2+2);
51 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR
);
53 for (i
= j
= 0; i
< str
->size
; i
++)
55 if (str
->data
[i
] == 0)
57 /* this is handled earlier */
58 ret
= gnutls_assert_val(GNUTLS_E_ASN1_DER_ERROR
);
62 if (str
->data
[i
] == ',' || str
->data
[i
] == '+' || str
->data
[i
] == '"'
63 || str
->data
[i
] == '\\' || str
->data
[i
] == '<' || str
->data
[i
] == '>'
64 || str
->data
[i
] == ';' || str
->data
[i
] == 0)
66 else if (i
==0 && str
->data
[i
] == '#')
68 else if (i
==0 && str
->data
[i
] == ' ')
70 else if (i
==(str
->size
-1) && str
->data
[i
] == ' ')
73 buffer
[j
++] = str
->data
[i
];
76 /* null terminate the string */
78 escaped
->data
= buffer
;
87 /* Parses an X509 DN in the asn1_struct, and puts the output into
88 * the string buf. The output is an LDAP encoded DN.
90 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
91 * That is to point in the rndSequence.
94 _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct
,
95 const char *asn1_rdn_name
, char *buf
,
98 gnutls_buffer_st out_str
;
100 char tmpbuffer1
[ASN1_MAX_NAME_SIZE
];
101 char tmpbuffer2
[ASN1_MAX_NAME_SIZE
];
102 char tmpbuffer3
[ASN1_MAX_NAME_SIZE
];
103 uint8_t value
[MAX_STRING_LEN
], *value2
= NULL
;
104 gnutls_datum_t td
, escaped
= {NULL
, 0};
105 const char *ldap_desc
;
106 char oid
[MAX_OID_SIZE
];
109 if (sizeof_buf
== NULL
)
112 return GNUTLS_E_INVALID_REQUEST
;
115 if (*sizeof_buf
> 0 && buf
)
120 _gnutls_buffer_init (&out_str
);
127 /* create a string like "tbsCertList.issuer.rdnSequence.?1"
129 if (asn1_rdn_name
[0] != 0)
130 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "%s.?%u", asn1_rdn_name
,
133 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "?%u", k1
);
135 len
= sizeof (value
) - 1;
136 result
= asn1_read_value (asn1_struct
, tmpbuffer1
, value
, &len
);
138 if (result
== ASN1_ELEMENT_NOT_FOUND
)
143 if (result
!= ASN1_VALUE_NOT_FOUND
)
146 result
= _gnutls_asn2err (result
);
153 { /* Move to the attibute type and values
157 if (tmpbuffer1
[0] != 0)
158 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "%s.?%u", tmpbuffer1
,
161 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "?%u", k2
);
163 /* Try to read the RelativeDistinguishedName attributes.
166 len
= sizeof (value
) - 1;
167 result
= asn1_read_value (asn1_struct
, tmpbuffer2
, value
, &len
);
169 if (result
== ASN1_ELEMENT_NOT_FOUND
)
171 if (result
!= ASN1_VALUE_NOT_FOUND
)
174 result
= _gnutls_asn2err (result
);
180 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
181 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".type");
183 len
= sizeof (oid
) - 1;
184 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, oid
, &len
);
186 if (result
== ASN1_ELEMENT_NOT_FOUND
)
188 else if (result
!= ASN1_SUCCESS
)
191 result
= _gnutls_asn2err (result
);
197 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
198 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".value");
201 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, NULL
, &len
);
202 if (result
!= ASN1_MEM_ERROR
)
205 result
= _gnutls_asn2err (result
);
209 value2
= gnutls_malloc (len
);
213 result
= GNUTLS_E_MEMORY_ERROR
;
217 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, value2
, &len
);
219 if (result
!= ASN1_SUCCESS
)
222 result
= _gnutls_asn2err (result
);
225 #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \
229 #define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( &out_str, x,y)) < 0) { \
233 /* The encodings of adjoining RelativeDistinguishedNames are separated
234 * by a comma character (',' ASCII 44).
237 /* Where there is a multi-valued RDN, the outputs from adjoining
238 * AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
242 { /* the first time do not append a comma */
244 { /* adjoining multi-value RDN */
253 ldap_desc
= gnutls_x509_dn_oid_name (oid
, GNUTLS_X509_DN_OID_RETURN_OID
);
256 STR_APPEND (ldap_desc
);
260 _gnutls_x509_dn_to_string (oid
, value2
, len
, &td
);
265 ("Cannot parse OID: '%s' with value '%s'\n",
266 oid
, _gnutls_bin2hex (value2
, len
, tmpbuffer3
, sizeof(tmpbuffer3
),
271 result
= str_escape(&td
, &escaped
);
278 DATA_APPEND (escaped
.data
, escaped
.size
);
279 _gnutls_free_datum (&td
);
280 _gnutls_free_datum (&escaped
);
281 gnutls_free (value2
);
290 if (out_str
.length
>= (unsigned int) *sizeof_buf
)
293 *sizeof_buf
= out_str
.length
+ 1;
294 result
= GNUTLS_E_SHORT_MEMORY_BUFFER
;
300 _gnutls_buffer_pop_data (&out_str
, buf
, sizeof_buf
);
301 buf
[*sizeof_buf
] = 0;
304 *sizeof_buf
= out_str
.length
;
309 gnutls_free (value2
);
310 _gnutls_free_datum (&escaped
);
311 _gnutls_buffer_clear (&out_str
);
315 /* Parses an X509 DN in the asn1_struct, and searches for the
316 * given OID in the DN.
318 * If raw_flag == 0, the output will be encoded in the LDAP way. (#hex for non printable)
319 * Otherwise the raw DER data are returned.
321 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
322 * That is to point in the rndSequence.
324 * indx specifies which OID to return. Ie 0 means return the first specified
325 * OID found, 1 the second etc.
328 _gnutls_x509_parse_dn_oid (ASN1_TYPE asn1_struct
,
329 const char *asn1_rdn_name
,
330 const char *given_oid
, int indx
,
331 unsigned int raw_flag
,
335 char tmpbuffer1
[ASN1_MAX_NAME_SIZE
];
336 char tmpbuffer2
[ASN1_MAX_NAME_SIZE
];
337 char tmpbuffer3
[ASN1_MAX_NAME_SIZE
];
340 char oid
[MAX_OID_SIZE
];
349 /* create a string like "tbsCertList.issuer.rdnSequence.?1"
351 if (asn1_rdn_name
[0] != 0)
352 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "%s.?%u", asn1_rdn_name
,
355 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "?%u", k1
);
357 len
= sizeof (value
) - 1;
358 result
= asn1_read_value (asn1_struct
, tmpbuffer1
, value
, &len
);
360 if (result
== ASN1_ELEMENT_NOT_FOUND
)
366 if (result
!= ASN1_VALUE_NOT_FOUND
)
369 result
= _gnutls_asn2err (result
);
376 { /* Move to the attibute type and values
380 if (tmpbuffer1
[0] != 0)
381 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "%s.?%u", tmpbuffer1
,
384 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "?%u", k2
);
386 /* Try to read the RelativeDistinguishedName attributes.
389 len
= sizeof (value
) - 1;
390 result
= asn1_read_value (asn1_struct
, tmpbuffer2
, value
, &len
);
392 if (result
== ASN1_ELEMENT_NOT_FOUND
)
396 if (result
!= ASN1_VALUE_NOT_FOUND
)
399 result
= _gnutls_asn2err (result
);
405 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
406 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".type");
408 len
= sizeof (oid
) - 1;
409 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, oid
, &len
);
411 if (result
== ASN1_ELEMENT_NOT_FOUND
)
413 else if (result
!= ASN1_SUCCESS
)
416 result
= _gnutls_asn2err (result
);
420 if (strcmp (oid
, given_oid
) == 0 && indx
== i
++)
421 { /* Found the OID */
425 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
426 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".value");
428 result
= _gnutls_x509_read_value(asn1_struct
, tmpbuffer3
, &td
);
443 { /* parse data. raw_flag == 0 */
445 _gnutls_x509_dn_to_string (oid
, td
.data
, td
.size
, out
);
447 _gnutls_free_datum(&td
);
456 } /* raw_flag == 0 */
466 result
= GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
473 /* Parses an X509 DN in the asn1_struct, and returns the requested
476 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
477 * That is to point in the rndSequence.
479 * indx specifies which OID to return. Ie 0 means return the first specified
480 * OID found, 1 the second etc.
483 _gnutls_x509_get_dn_oid (ASN1_TYPE asn1_struct
,
484 const char *asn1_rdn_name
,
485 int indx
, void *_oid
, size_t * sizeof_oid
)
488 char tmpbuffer1
[ASN1_MAX_NAME_SIZE
];
489 char tmpbuffer2
[ASN1_MAX_NAME_SIZE
];
490 char tmpbuffer3
[ASN1_MAX_NAME_SIZE
];
492 char oid
[MAX_OID_SIZE
];
501 /* create a string like "tbsCertList.issuer.rdnSequence.?1"
503 if (asn1_rdn_name
[0] != 0)
504 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "%s.?%u", asn1_rdn_name
,
507 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "?%u", k1
);
509 len
= sizeof (value
) - 1;
510 result
= asn1_read_value (asn1_struct
, tmpbuffer1
, value
, &len
);
512 if (result
== ASN1_ELEMENT_NOT_FOUND
)
518 if (result
!= ASN1_VALUE_NOT_FOUND
)
521 result
= _gnutls_asn2err (result
);
528 { /* Move to the attibute type and values
532 if (tmpbuffer1
[0] != 0)
533 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "%s.?%u", tmpbuffer1
,
536 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "?%u", k2
);
538 /* Try to read the RelativeDistinguishedName attributes.
541 len
= sizeof (value
) - 1;
542 result
= asn1_read_value (asn1_struct
, tmpbuffer2
, value
, &len
);
544 if (result
== ASN1_ELEMENT_NOT_FOUND
)
548 if (result
!= ASN1_VALUE_NOT_FOUND
)
551 result
= _gnutls_asn2err (result
);
557 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
558 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".type");
560 len
= sizeof (oid
) - 1;
561 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, oid
, &len
);
563 if (result
== ASN1_ELEMENT_NOT_FOUND
)
565 else if (result
!= ASN1_SUCCESS
)
568 result
= _gnutls_asn2err (result
);
573 { /* Found the OID */
575 len
= strlen (oid
) + 1;
577 if (*sizeof_oid
< (unsigned) len
)
581 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
584 memcpy (_oid
, oid
, len
);
585 *sizeof_oid
= len
- 1;
597 result
= GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
603 /* This will write the AttributeTypeAndValue field. The data must be already DER encoded.
604 * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute.
605 * In all cases only one value is written.
608 _gnutls_x509_write_attribute (const char *given_oid
,
609 ASN1_TYPE asn1_struct
, const char *where
,
610 const void *_data
, int sizeof_data
)
615 /* write the data (value)
618 _gnutls_str_cpy (tmp
, sizeof (tmp
), where
);
619 _gnutls_str_cat (tmp
, sizeof (tmp
), ".value");
621 result
= asn1_write_value (asn1_struct
, tmp
, _data
, sizeof_data
);
625 return _gnutls_asn2err (result
);
630 _gnutls_str_cpy (tmp
, sizeof (tmp
), where
);
631 _gnutls_str_cat (tmp
, sizeof (tmp
), ".type");
633 result
= asn1_write_value (asn1_struct
, tmp
, given_oid
, 1);
634 if (result
!= ASN1_SUCCESS
)
637 return _gnutls_asn2err (result
);
644 /* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue
647 * octet_string should be non-zero if we are to decode octet strings after
650 * The output is allocated and stored in value.
653 _gnutls_x509_decode_and_read_attribute (ASN1_TYPE asn1_struct
,
654 const char *where
, char *oid
,
655 int oid_size
, gnutls_datum_t
* value
,
656 int multi
, int octet_string
)
663 _gnutls_str_cpy (tmpbuffer
, sizeof (tmpbuffer
), where
);
664 _gnutls_str_cat (tmpbuffer
, sizeof (tmpbuffer
), ".type");
667 result
= asn1_read_value (asn1_struct
, tmpbuffer
, oid
, &len
);
669 if (result
!= ASN1_SUCCESS
)
672 result
= _gnutls_asn2err (result
);
679 _gnutls_str_cpy (tmpbuffer
, sizeof (tmpbuffer
), where
);
680 _gnutls_str_cat (tmpbuffer
, sizeof (tmpbuffer
), ".value");
683 _gnutls_str_cat (tmpbuffer
, sizeof (tmpbuffer
), "s.?1"); /* .values.?1 */
686 result
= _gnutls_x509_read_string (asn1_struct
, tmpbuffer
, value
, ASN1_ETYPE_OCTET_STRING
);
688 result
= _gnutls_x509_read_value (asn1_struct
, tmpbuffer
, value
);
699 /* Sets an X509 DN in the asn1_struct, and puts the given OID in the DN.
700 * The input is assumed to be raw data.
702 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer".
703 * That is to point before the rndSequence.
707 _gnutls_x509_set_dn_oid (ASN1_TYPE asn1_struct
,
708 const char *asn1_name
, const char *given_oid
,
709 int raw_flag
, const char *name
, int sizeof_name
)
712 char tmp
[ASN1_MAX_NAME_SIZE
], asn1_rdn_name
[ASN1_MAX_NAME_SIZE
];
714 if (sizeof_name
== 0 || name
== NULL
)
717 return GNUTLS_E_INVALID_REQUEST
;
720 /* create the rdnSequence
722 result
= asn1_write_value (asn1_struct
, asn1_name
, "rdnSequence", 1);
723 if (result
!= ASN1_SUCCESS
)
726 return _gnutls_asn2err (result
);
729 _gnutls_str_cpy (asn1_rdn_name
, sizeof (asn1_rdn_name
), asn1_name
);
730 _gnutls_str_cat (asn1_rdn_name
, sizeof (asn1_rdn_name
), ".rdnSequence");
732 /* create a new element
734 result
= asn1_write_value (asn1_struct
, asn1_rdn_name
, "NEW", 1);
735 if (result
!= ASN1_SUCCESS
)
738 return _gnutls_asn2err (result
);
741 _gnutls_str_cpy (tmp
, sizeof (tmp
), asn1_rdn_name
);
742 _gnutls_str_cat (tmp
, sizeof (tmp
), ".?LAST");
744 /* create the set with only one element
746 result
= asn1_write_value (asn1_struct
, tmp
, "NEW", 1);
747 if (result
!= ASN1_SUCCESS
)
750 return _gnutls_asn2err (result
);
754 /* Encode and write the data
756 _gnutls_str_cpy (tmp
, sizeof (tmp
), asn1_rdn_name
);
757 _gnutls_str_cat (tmp
, sizeof (tmp
), ".?LAST.?LAST");
762 _gnutls_x509_encode_and_write_attribute (given_oid
,
764 tmp
, name
, sizeof_name
, 0);
769 _gnutls_x509_write_attribute (given_oid
, asn1_struct
,
770 tmp
, name
, sizeof_name
);
783 * gnutls_x509_dn_init:
784 * @dn: the object to be initialized
786 * This function initializes a #gnutls_x509_dn_t structure.
788 * The object returned must be deallocated using
789 * gnutls_x509_dn_deinit().
791 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
792 * negative error value.
797 gnutls_x509_dn_init (gnutls_x509_dn_t
* dn
)
800 ASN1_TYPE tmpdn
= ASN1_TYPE_EMPTY
;
803 asn1_create_element (_gnutls_get_pkix (),
804 "PKIX1.Name", &tmpdn
)) != ASN1_SUCCESS
)
807 return _gnutls_asn2err (result
);
816 * gnutls_x509_dn_import:
817 * @dn: the structure that will hold the imported DN
818 * @data: should contain a DER encoded RDN sequence
820 * This function parses an RDN sequence and stores the result to a
821 * #gnutls_x509_dn_t structure. The structure must have been initialized
822 * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to
825 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
826 * negative error value.
831 gnutls_x509_dn_import (gnutls_x509_dn_t dn
, const gnutls_datum_t
* data
)
834 char err
[ASN1_MAX_ERROR_DESCRIPTION_SIZE
];
836 result
= asn1_der_decoding ((ASN1_TYPE
*) & dn
,
837 data
->data
, data
->size
, err
);
838 if (result
!= ASN1_SUCCESS
)
840 /* couldn't decode DER */
841 _gnutls_debug_log ("ASN.1 Decoding error: %s\n", err
);
843 return _gnutls_asn2err (result
);
850 * gnutls_x509_dn_deinit:
851 * @dn: a DN uint8_t object pointer.
853 * This function deallocates the DN object as returned by
854 * gnutls_x509_dn_import().
859 gnutls_x509_dn_deinit (gnutls_x509_dn_t dn
)
861 asn1_delete_structure ((ASN1_TYPE
*) & dn
);
865 * gnutls_x509_rdn_get:
866 * @idn: should contain a DER encoded RDN sequence
867 * @buf: a pointer to a structure to hold the peer's name
868 * @sizeof_buf: holds the size of @buf
870 * This function will return the name of the given RDN sequence. The
871 * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in
874 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
875 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
876 * updated if the provided buffer is not long enough, otherwise a
877 * negative error value.
880 gnutls_x509_rdn_get (const gnutls_datum_t
* idn
,
881 char *buf
, size_t * sizeof_buf
)
884 ASN1_TYPE dn
= ASN1_TYPE_EMPTY
;
889 return GNUTLS_E_INVALID_REQUEST
;
897 asn1_create_element (_gnutls_get_pkix (),
898 "PKIX1.Name", &dn
)) != ASN1_SUCCESS
)
901 return _gnutls_asn2err (result
);
904 result
= asn1_der_decoding (&dn
, idn
->data
, idn
->size
, NULL
);
905 if (result
!= ASN1_SUCCESS
)
907 /* couldn't decode DER */
909 asn1_delete_structure (&dn
);
910 return _gnutls_asn2err (result
);
913 result
= _gnutls_x509_parse_dn (dn
, "rdnSequence", buf
, sizeof_buf
);
915 asn1_delete_structure (&dn
);
921 * gnutls_x509_rdn_get_by_oid:
922 * @idn: should contain a DER encoded RDN sequence
923 * @oid: an Object Identifier
924 * @indx: In case multiple same OIDs exist in the RDN indicates which
925 * to send. Use 0 for the first one.
926 * @raw_flag: If non-zero then the raw DER data are returned.
927 * @buf: a pointer to a structure to hold the peer's name
928 * @sizeof_buf: holds the size of @buf
930 * This function will return the name of the given Object identifier,
931 * of the RDN sequence. The name will be encoded using the rules
934 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
935 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
936 * updated if the provided buffer is not long enough, otherwise a
937 * negative error value.
940 gnutls_x509_rdn_get_by_oid (const gnutls_datum_t
* idn
, const char *oid
,
941 int indx
, unsigned int raw_flag
,
942 void *buf
, size_t * sizeof_buf
)
945 ASN1_TYPE dn
= ASN1_TYPE_EMPTY
;
950 return GNUTLS_E_INVALID_REQUEST
;
954 asn1_create_element (_gnutls_get_pkix (),
955 "PKIX1.Name", &dn
)) != ASN1_SUCCESS
)
958 return _gnutls_asn2err (result
);
961 result
= asn1_der_decoding (&dn
, idn
->data
, idn
->size
, NULL
);
962 if (result
!= ASN1_SUCCESS
)
964 /* couldn't decode DER */
966 asn1_delete_structure (&dn
);
967 return _gnutls_asn2err (result
);
971 _gnutls_x509_parse_dn_oid (dn
, "rdnSequence", oid
, indx
,
974 asn1_delete_structure (&dn
);
976 return gnutls_assert_val(result
);
978 return _gnutls_strdatum_to_buf (&td
, buf
, sizeof_buf
);
982 * gnutls_x509_rdn_get_oid:
983 * @idn: should contain a DER encoded RDN sequence
984 * @indx: Indicates which OID to return. Use 0 for the first one.
985 * @buf: a pointer to a structure to hold the peer's name OID
986 * @sizeof_buf: holds the size of @buf
988 * This function will return the specified Object identifier, of the
991 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
992 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
993 * updated if the provided buffer is not long enough, otherwise a
994 * negative error value.
999 gnutls_x509_rdn_get_oid (const gnutls_datum_t
* idn
,
1000 int indx
, void *buf
, size_t * sizeof_buf
)
1003 ASN1_TYPE dn
= ASN1_TYPE_EMPTY
;
1005 if (sizeof_buf
== 0)
1007 return GNUTLS_E_INVALID_REQUEST
;
1011 asn1_create_element (_gnutls_get_pkix (),
1012 "PKIX1.Name", &dn
)) != ASN1_SUCCESS
)
1015 return _gnutls_asn2err (result
);
1018 result
= asn1_der_decoding (&dn
, idn
->data
, idn
->size
, NULL
);
1019 if (result
!= ASN1_SUCCESS
)
1021 /* couldn't decode DER */
1023 asn1_delete_structure (&dn
);
1024 return _gnutls_asn2err (result
);
1027 result
= _gnutls_x509_get_dn_oid (dn
, "rdnSequence", indx
, buf
, sizeof_buf
);
1029 asn1_delete_structure (&dn
);
1035 * Compares the DER encoded part of a DN.
1037 * FIXME: use a real DN comparison algorithm.
1039 * Returns 1 if the DN's match and (0) if they don't match. Otherwise
1040 * a negative error code is returned to indicate error.
1043 _gnutls_x509_compare_raw_dn (const gnutls_datum_t
* dn1
,
1044 const gnutls_datum_t
* dn2
)
1047 if (dn1
->size
!= dn2
->size
)
1052 if (memcmp (dn1
->data
, dn2
->data
, dn2
->size
) != 0)
1057 return 1; /* they match */
1061 * gnutls_x509_dn_export:
1062 * @dn: Holds the uint8_t DN object
1063 * @format: the format of output params. One of PEM or DER.
1064 * @output_data: will contain a DN PEM or DER encoded
1065 * @output_data_size: holds the size of output_data (and will be
1066 * replaced by the actual size of parameters)
1068 * This function will export the DN to DER or PEM format.
1070 * If the buffer provided is not long enough to hold the output, then
1071 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
1074 * If the structure is PEM encoded, it will have a header
1077 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1078 * negative error value.
1081 gnutls_x509_dn_export (gnutls_x509_dn_t dn
,
1082 gnutls_x509_crt_fmt_t format
, void *output_data
,
1083 size_t * output_data_size
)
1085 ASN1_TYPE asn1
= dn
;
1090 return GNUTLS_E_INVALID_REQUEST
;
1093 return _gnutls_x509_export_int_named (asn1
, "rdnSequence",
1095 output_data
, output_data_size
);
1099 * gnutls_x509_dn_export2:
1100 * @dn: Holds the uint8_t DN object
1101 * @format: the format of output params. One of PEM or DER.
1102 * @out: will contain a DN PEM or DER encoded
1104 * This function will export the DN to DER or PEM format.
1106 * The output buffer is allocated using gnutls_malloc().
1108 * If the structure is PEM encoded, it will have a header
1111 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1112 * negative error value.
1115 gnutls_x509_dn_export2 (gnutls_x509_dn_t dn
,
1116 gnutls_x509_crt_fmt_t format
, gnutls_datum_t
*out
)
1118 ASN1_TYPE asn1
= dn
;
1123 return GNUTLS_E_INVALID_REQUEST
;
1126 return _gnutls_x509_export_int_named2 (asn1
, "rdnSequence",
1127 format
, "NAME", out
);