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 (char *str
, char *buffer
, unsigned int buffer_size
)
43 if (str
== NULL
|| buffer
== NULL
)
46 str_length
= MIN (strlen (str
), buffer_size
- 1);
48 for (i
= j
= 0; i
< str_length
; i
++)
50 if (str
[i
] == ',' || str
[i
] == '+' || str
[i
] == '"'
51 || str
[i
] == '\\' || str
[i
] == '<' || str
[i
] == '>'
58 /* null terminate the string */
64 /* Parses an X509 DN in the asn1_struct, and puts the output into
65 * the string buf. The output is an LDAP encoded DN.
67 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
68 * That is to point in the rndSequence.
71 _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct
,
72 const char *asn1_rdn_name
, char *buf
,
75 gnutls_buffer_st out_str
;
77 char tmpbuffer1
[ASN1_MAX_NAME_SIZE
];
78 char tmpbuffer2
[ASN1_MAX_NAME_SIZE
];
79 char tmpbuffer3
[ASN1_MAX_NAME_SIZE
];
80 uint8_t value
[MAX_STRING_LEN
], *value2
= NULL
;
82 const char *ldap_desc
;
83 char oid
[MAX_OID_SIZE
];
86 size_t sizeof_string
, sizeof_escaped
;
88 if (sizeof_buf
== NULL
)
91 return GNUTLS_E_INVALID_REQUEST
;
94 if (*sizeof_buf
> 0 && buf
)
99 _gnutls_buffer_init (&out_str
);
106 /* create a string like "tbsCertList.issuer.rdnSequence.?1"
108 if (asn1_rdn_name
[0] != 0)
109 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "%s.?%u", asn1_rdn_name
,
112 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "?%u", k1
);
114 len
= sizeof (value
) - 1;
115 result
= asn1_read_value (asn1_struct
, tmpbuffer1
, value
, &len
);
117 if (result
== ASN1_ELEMENT_NOT_FOUND
)
122 if (result
!= ASN1_VALUE_NOT_FOUND
)
125 result
= _gnutls_asn2err (result
);
132 { /* Move to the attibute type and values
136 if (tmpbuffer1
[0] != 0)
137 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "%s.?%u", tmpbuffer1
,
140 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "?%u", k2
);
142 /* Try to read the RelativeDistinguishedName attributes.
145 len
= sizeof (value
) - 1;
146 result
= asn1_read_value (asn1_struct
, tmpbuffer2
, value
, &len
);
148 if (result
== ASN1_ELEMENT_NOT_FOUND
)
150 if (result
!= ASN1_VALUE_NOT_FOUND
)
153 result
= _gnutls_asn2err (result
);
159 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
160 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".type");
162 len
= sizeof (oid
) - 1;
163 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, oid
, &len
);
165 if (result
== ASN1_ELEMENT_NOT_FOUND
)
167 else if (result
!= ASN1_SUCCESS
)
170 result
= _gnutls_asn2err (result
);
176 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
177 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".value");
180 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, NULL
, &len
);
181 if (result
!= ASN1_MEM_ERROR
)
184 result
= _gnutls_asn2err (result
);
188 value2
= gnutls_malloc (len
);
192 result
= GNUTLS_E_MEMORY_ERROR
;
196 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, value2
, &len
);
198 if (result
!= ASN1_SUCCESS
)
201 result
= _gnutls_asn2err (result
);
204 #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \
208 /* The encodings of adjoining RelativeDistinguishedNames are separated
209 * by a comma character (',' ASCII 44).
212 /* Where there is a multi-valued RDN, the outputs from adjoining
213 * AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
217 { /* the first time do not append a comma */
219 { /* adjoining multi-value RDN */
228 ldap_desc
= gnutls_x509_dn_oid_name (oid
, GNUTLS_X509_DN_OID_RETURN_OID
);
229 printable
= _gnutls_x509_oid_data_printable (oid
);
231 /* leading #, hex encoded value and terminating NULL */
232 sizeof_escaped
= 2 * len
+ 2;
234 escaped
= gnutls_malloc (sizeof_escaped
);
238 result
= GNUTLS_E_MEMORY_ERROR
;
242 sizeof_string
= 2 * len
+ 2; /* in case it is not printable */
244 string
= gnutls_malloc (sizeof_string
);
248 result
= GNUTLS_E_MEMORY_ERROR
;
252 STR_APPEND (ldap_desc
);
258 _gnutls_x509_oid_data2string (oid
,
260 string
, &sizeof_string
);
262 if (!printable
|| result
< 0)
264 _gnutls_x509_data2hex (value2
, len
, string
, &sizeof_string
);
270 ("Found OID: '%s' with value '%s'\n",
271 oid
, _gnutls_bin2hex (value2
, len
, escaped
, sizeof_escaped
,
275 STR_APPEND (str_escape (string
, escaped
, sizeof_escaped
));
276 gnutls_free (string
);
279 gnutls_free (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 (string
);
311 gnutls_free (escaped
);
312 _gnutls_buffer_clear (&out_str
);
316 /* Parses an X509 DN in the asn1_struct, and searches for the
317 * given OID in the DN.
319 * If raw_flag == 0, the output will be encoded in the LDAP way. (#hex for non printable)
320 * Otherwise the raw DER data are returned.
322 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
323 * That is to point in the rndSequence.
325 * indx specifies which OID to return. Ie 0 means return the first specified
326 * OID found, 1 the second etc.
329 _gnutls_x509_parse_dn_oid (ASN1_TYPE asn1_struct
,
330 const char *asn1_rdn_name
,
331 const char *given_oid
, int indx
,
332 unsigned int raw_flag
,
333 void *buf
, size_t * sizeof_buf
)
336 char tmpbuffer1
[ASN1_MAX_NAME_SIZE
];
337 char tmpbuffer2
[ASN1_MAX_NAME_SIZE
];
338 char tmpbuffer3
[ASN1_MAX_NAME_SIZE
];
340 char oid
[MAX_OID_SIZE
];
355 /* create a string like "tbsCertList.issuer.rdnSequence.?1"
357 if (asn1_rdn_name
[0] != 0)
358 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "%s.?%u", asn1_rdn_name
,
361 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "?%u", k1
);
363 len
= sizeof (value
) - 1;
364 result
= asn1_read_value (asn1_struct
, tmpbuffer1
, value
, &len
);
366 if (result
== ASN1_ELEMENT_NOT_FOUND
)
372 if (result
!= ASN1_VALUE_NOT_FOUND
)
375 result
= _gnutls_asn2err (result
);
382 { /* Move to the attibute type and values
386 if (tmpbuffer1
[0] != 0)
387 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "%s.?%u", tmpbuffer1
,
390 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "?%u", k2
);
392 /* Try to read the RelativeDistinguishedName attributes.
395 len
= sizeof (value
) - 1;
396 result
= asn1_read_value (asn1_struct
, tmpbuffer2
, value
, &len
);
398 if (result
== ASN1_ELEMENT_NOT_FOUND
)
402 if (result
!= ASN1_VALUE_NOT_FOUND
)
405 result
= _gnutls_asn2err (result
);
411 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
412 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".type");
414 len
= sizeof (oid
) - 1;
415 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, oid
, &len
);
417 if (result
== ASN1_ELEMENT_NOT_FOUND
)
419 else if (result
!= ASN1_SUCCESS
)
422 result
= _gnutls_asn2err (result
);
426 if (strcmp (oid
, given_oid
) == 0 && indx
== i
++)
427 { /* Found the OID */
431 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
432 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".value");
435 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, buf
, &len
);
437 if (result
!= ASN1_SUCCESS
)
440 if (result
== ASN1_MEM_ERROR
)
442 result
= _gnutls_asn2err (result
);
448 if ((unsigned) len
> *sizeof_buf
)
451 result
= GNUTLS_E_SHORT_MEMORY_BUFFER
;
460 { /* parse data. raw_flag == 0 */
461 printable
= _gnutls_x509_oid_data_printable (oid
);
465 _gnutls_x509_oid_data2string (oid
, buf
, len
,
469 _gnutls_x509_data2hex (buf
, len
, cbuf
, sizeof_buf
);
479 } /* raw_flag == 0 */
489 result
= GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
496 /* Parses an X509 DN in the asn1_struct, and returns the requested
499 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
500 * That is to point in the rndSequence.
502 * indx specifies which OID to return. Ie 0 means return the first specified
503 * OID found, 1 the second etc.
506 _gnutls_x509_get_dn_oid (ASN1_TYPE asn1_struct
,
507 const char *asn1_rdn_name
,
508 int indx
, void *_oid
, size_t * sizeof_oid
)
511 char tmpbuffer1
[ASN1_MAX_NAME_SIZE
];
512 char tmpbuffer2
[ASN1_MAX_NAME_SIZE
];
513 char tmpbuffer3
[ASN1_MAX_NAME_SIZE
];
515 char oid
[MAX_OID_SIZE
];
524 /* create a string like "tbsCertList.issuer.rdnSequence.?1"
526 if (asn1_rdn_name
[0] != 0)
527 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "%s.?%u", asn1_rdn_name
,
530 snprintf (tmpbuffer1
, sizeof (tmpbuffer1
), "?%u", k1
);
532 len
= sizeof (value
) - 1;
533 result
= asn1_read_value (asn1_struct
, tmpbuffer1
, value
, &len
);
535 if (result
== ASN1_ELEMENT_NOT_FOUND
)
541 if (result
!= ASN1_VALUE_NOT_FOUND
)
544 result
= _gnutls_asn2err (result
);
551 { /* Move to the attibute type and values
555 if (tmpbuffer1
[0] != 0)
556 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "%s.?%u", tmpbuffer1
,
559 snprintf (tmpbuffer2
, sizeof (tmpbuffer2
), "?%u", k2
);
561 /* Try to read the RelativeDistinguishedName attributes.
564 len
= sizeof (value
) - 1;
565 result
= asn1_read_value (asn1_struct
, tmpbuffer2
, value
, &len
);
567 if (result
== ASN1_ELEMENT_NOT_FOUND
)
571 if (result
!= ASN1_VALUE_NOT_FOUND
)
574 result
= _gnutls_asn2err (result
);
580 _gnutls_str_cpy (tmpbuffer3
, sizeof (tmpbuffer3
), tmpbuffer2
);
581 _gnutls_str_cat (tmpbuffer3
, sizeof (tmpbuffer3
), ".type");
583 len
= sizeof (oid
) - 1;
584 result
= asn1_read_value (asn1_struct
, tmpbuffer3
, oid
, &len
);
586 if (result
== ASN1_ELEMENT_NOT_FOUND
)
588 else if (result
!= ASN1_SUCCESS
)
591 result
= _gnutls_asn2err (result
);
596 { /* Found the OID */
598 len
= strlen (oid
) + 1;
600 if (*sizeof_oid
< (unsigned) len
)
604 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
607 memcpy (_oid
, oid
, len
);
608 *sizeof_oid
= len
- 1;
620 result
= GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
626 /* This will encode and write the AttributeTypeAndValue field.
627 * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute.
628 * In all cases only one value is written.
631 _gnutls_x509_encode_and_write_attribute (const char *given_oid
,
632 ASN1_TYPE asn1_struct
,
635 int sizeof_data
, int multi
)
637 const char *val_name
;
638 const uint8_t *data
= _data
;
644 /* Find how to encode the data.
646 val_name
= _gnutls_x509_oid2asn_string (given_oid
);
647 if (val_name
== NULL
)
650 _gnutls_debug_log ("Cannot find OID: %s\n", given_oid
);
651 return GNUTLS_E_X509_UNSUPPORTED_OID
;
654 result
= asn1_create_element (_gnutls_get_pkix (), val_name
, &c2
);
655 if (result
!= ASN1_SUCCESS
)
658 return _gnutls_asn2err (result
);
663 if ((result
= _gnutls_x509_oid_data_choice (given_oid
)) > 0)
665 const char *string_type
;
668 string_type
= "printableString";
670 /* Check if the data is plain ascii, and use
671 * the UTF8 string type if not.
673 for (i
= 0; i
< sizeof_data
; i
++)
675 if (!isascii (data
[i
]))
677 string_type
= "utf8String";
682 /* if the type is a CHOICE then write the
685 result
= asn1_write_value (c2
, "", string_type
, 1);
686 if (result
!= ASN1_SUCCESS
)
689 result
= _gnutls_asn2err (result
);
693 _gnutls_str_cpy (tmp
, sizeof (tmp
), string_type
);
696 result
= asn1_write_value (c2
, tmp
, data
, sizeof_data
);
697 if (result
!= ASN1_SUCCESS
)
700 result
= _gnutls_asn2err (result
);
705 /* write the data (value)
708 _gnutls_str_cpy (tmp
, sizeof (tmp
), where
);
709 _gnutls_str_cat (tmp
, sizeof (tmp
), ".value");
712 { /* if not writing an AttributeTypeAndValue, but an Attribute */
713 _gnutls_str_cat (tmp
, sizeof (tmp
), "s"); /* values */
715 result
= asn1_write_value (asn1_struct
, tmp
, "NEW", 1);
716 if (result
!= ASN1_SUCCESS
)
719 result
= _gnutls_asn2err (result
);
723 _gnutls_str_cat (tmp
, sizeof (tmp
), ".?LAST");
727 result
= _gnutls_x509_der_encode_and_copy (c2
, "", asn1_struct
, tmp
, 0);
731 result
= _gnutls_asn2err (result
);
737 _gnutls_str_cpy (tmp
, sizeof (tmp
), where
);
738 _gnutls_str_cat (tmp
, sizeof (tmp
), ".type");
740 result
= asn1_write_value (asn1_struct
, tmp
, given_oid
, 1);
741 if (result
!= ASN1_SUCCESS
)
744 result
= _gnutls_asn2err (result
);
751 asn1_delete_structure (&c2
);
755 /* This will write the AttributeTypeAndValue field. The data must be already DER encoded.
756 * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute.
757 * In all cases only one value is written.
760 _gnutls_x509_write_attribute (const char *given_oid
,
761 ASN1_TYPE asn1_struct
, const char *where
,
762 const void *_data
, int sizeof_data
)
767 /* write the data (value)
770 _gnutls_str_cpy (tmp
, sizeof (tmp
), where
);
771 _gnutls_str_cat (tmp
, sizeof (tmp
), ".value");
773 result
= asn1_write_value (asn1_struct
, tmp
, _data
, sizeof_data
);
777 return _gnutls_asn2err (result
);
782 _gnutls_str_cpy (tmp
, sizeof (tmp
), where
);
783 _gnutls_str_cat (tmp
, sizeof (tmp
), ".type");
785 result
= asn1_write_value (asn1_struct
, tmp
, given_oid
, 1);
786 if (result
!= ASN1_SUCCESS
)
789 return _gnutls_asn2err (result
);
796 /* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue
799 * octet_string should be non (0) if we are to decode octet strings after
802 * The output is allocated and stored in value.
805 _gnutls_x509_decode_and_read_attribute (ASN1_TYPE asn1_struct
,
806 const char *where
, char *oid
,
807 int oid_size
, gnutls_datum_t
* value
,
808 int multi
, int octet_string
)
815 _gnutls_str_cpy (tmpbuffer
, sizeof (tmpbuffer
), where
);
816 _gnutls_str_cat (tmpbuffer
, sizeof (tmpbuffer
), ".type");
819 result
= asn1_read_value (asn1_struct
, tmpbuffer
, oid
, &len
);
821 if (result
!= ASN1_SUCCESS
)
824 result
= _gnutls_asn2err (result
);
831 _gnutls_str_cpy (tmpbuffer
, sizeof (tmpbuffer
), where
);
832 _gnutls_str_cat (tmpbuffer
, sizeof (tmpbuffer
), ".value");
835 _gnutls_str_cat (tmpbuffer
, sizeof (tmpbuffer
), "s.?1"); /* .values.?1 */
838 _gnutls_x509_read_value (asn1_struct
, tmpbuffer
, value
, octet_string
);
849 /* Sets an X509 DN in the asn1_struct, and puts the given OID in the DN.
850 * The input is assumed to be raw data.
852 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer".
853 * That is to point before the rndSequence.
857 _gnutls_x509_set_dn_oid (ASN1_TYPE asn1_struct
,
858 const char *asn1_name
, const char *given_oid
,
859 int raw_flag
, const char *name
, int sizeof_name
)
862 char tmp
[ASN1_MAX_NAME_SIZE
], asn1_rdn_name
[ASN1_MAX_NAME_SIZE
];
864 if (sizeof_name
== 0 || name
== NULL
)
867 return GNUTLS_E_INVALID_REQUEST
;
870 /* create the rdnSequence
872 result
= asn1_write_value (asn1_struct
, asn1_name
, "rdnSequence", 1);
873 if (result
!= ASN1_SUCCESS
)
876 return _gnutls_asn2err (result
);
879 _gnutls_str_cpy (asn1_rdn_name
, sizeof (asn1_rdn_name
), asn1_name
);
880 _gnutls_str_cat (asn1_rdn_name
, sizeof (asn1_rdn_name
), ".rdnSequence");
882 /* create a new element
884 result
= asn1_write_value (asn1_struct
, asn1_rdn_name
, "NEW", 1);
885 if (result
!= ASN1_SUCCESS
)
888 return _gnutls_asn2err (result
);
891 _gnutls_str_cpy (tmp
, sizeof (tmp
), asn1_rdn_name
);
892 _gnutls_str_cat (tmp
, sizeof (tmp
), ".?LAST");
894 /* create the set with only one element
896 result
= asn1_write_value (asn1_struct
, tmp
, "NEW", 1);
897 if (result
!= ASN1_SUCCESS
)
900 return _gnutls_asn2err (result
);
904 /* Encode and write the data
906 _gnutls_str_cpy (tmp
, sizeof (tmp
), asn1_rdn_name
);
907 _gnutls_str_cat (tmp
, sizeof (tmp
), ".?LAST.?LAST");
912 _gnutls_x509_encode_and_write_attribute (given_oid
,
914 tmp
, name
, sizeof_name
, 0);
919 _gnutls_x509_write_attribute (given_oid
, asn1_struct
,
920 tmp
, name
, sizeof_name
);
933 * gnutls_x509_dn_init:
934 * @dn: the object to be initialized
936 * This function initializes a #gnutls_x509_dn_t structure.
938 * The object returned must be deallocated using
939 * gnutls_x509_dn_deinit().
941 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
942 * negative error value.
947 gnutls_x509_dn_init (gnutls_x509_dn_t
* dn
)
950 ASN1_TYPE tmpdn
= ASN1_TYPE_EMPTY
;
953 asn1_create_element (_gnutls_get_pkix (),
954 "PKIX1.Name", &tmpdn
)) != ASN1_SUCCESS
)
957 return _gnutls_asn2err (result
);
966 * gnutls_x509_dn_import:
967 * @dn: the structure that will hold the imported DN
968 * @data: should contain a DER encoded RDN sequence
970 * This function parses an RDN sequence and stores the result to a
971 * #gnutls_x509_dn_t structure. The structure must have been initialized
972 * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to
975 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
976 * negative error value.
981 gnutls_x509_dn_import (gnutls_x509_dn_t dn
, const gnutls_datum_t
* data
)
984 char err
[ASN1_MAX_ERROR_DESCRIPTION_SIZE
];
986 result
= asn1_der_decoding ((ASN1_TYPE
*) & dn
,
987 data
->data
, data
->size
, err
);
988 if (result
!= ASN1_SUCCESS
)
990 /* couldn't decode DER */
991 _gnutls_debug_log ("ASN.1 Decoding error: %s\n", err
);
993 return _gnutls_asn2err (result
);
1000 * gnutls_x509_dn_deinit:
1001 * @dn: a DN uint8_t object pointer.
1003 * This function deallocates the DN object as returned by
1004 * gnutls_x509_dn_import().
1009 gnutls_x509_dn_deinit (gnutls_x509_dn_t dn
)
1011 asn1_delete_structure ((ASN1_TYPE
*) & dn
);
1015 * gnutls_x509_rdn_get:
1016 * @idn: should contain a DER encoded RDN sequence
1017 * @buf: a pointer to a structure to hold the peer's name
1018 * @sizeof_buf: holds the size of @buf
1020 * This function will return the name of the given RDN sequence. The
1021 * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in
1024 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
1025 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
1026 * updated if the provided buffer is not long enough, otherwise a
1027 * negative error value.
1030 gnutls_x509_rdn_get (const gnutls_datum_t
* idn
,
1031 char *buf
, size_t * sizeof_buf
)
1034 ASN1_TYPE dn
= ASN1_TYPE_EMPTY
;
1036 if (sizeof_buf
== 0)
1039 return GNUTLS_E_INVALID_REQUEST
;
1047 asn1_create_element (_gnutls_get_pkix (),
1048 "PKIX1.Name", &dn
)) != ASN1_SUCCESS
)
1051 return _gnutls_asn2err (result
);
1054 result
= asn1_der_decoding (&dn
, idn
->data
, idn
->size
, NULL
);
1055 if (result
!= ASN1_SUCCESS
)
1057 /* couldn't decode DER */
1059 asn1_delete_structure (&dn
);
1060 return _gnutls_asn2err (result
);
1063 result
= _gnutls_x509_parse_dn (dn
, "rdnSequence", buf
, sizeof_buf
);
1065 asn1_delete_structure (&dn
);
1071 * gnutls_x509_rdn_get_by_oid:
1072 * @idn: should contain a DER encoded RDN sequence
1073 * @oid: an Object Identifier
1074 * @indx: In case multiple same OIDs exist in the RDN indicates which
1075 * to send. Use 0 for the first one.
1076 * @raw_flag: If non (0) then the raw DER data are returned.
1077 * @buf: a pointer to a structure to hold the peer's name
1078 * @sizeof_buf: holds the size of @buf
1080 * This function will return the name of the given Object identifier,
1081 * of the RDN sequence. The name will be encoded using the rules
1084 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
1085 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
1086 * updated if the provided buffer is not long enough, otherwise a
1087 * negative error value.
1090 gnutls_x509_rdn_get_by_oid (const gnutls_datum_t
* idn
, const char *oid
,
1091 int indx
, unsigned int raw_flag
,
1092 void *buf
, size_t * sizeof_buf
)
1095 ASN1_TYPE dn
= ASN1_TYPE_EMPTY
;
1097 if (sizeof_buf
== 0)
1099 return GNUTLS_E_INVALID_REQUEST
;
1103 asn1_create_element (_gnutls_get_pkix (),
1104 "PKIX1.Name", &dn
)) != ASN1_SUCCESS
)
1107 return _gnutls_asn2err (result
);
1110 result
= asn1_der_decoding (&dn
, idn
->data
, idn
->size
, NULL
);
1111 if (result
!= ASN1_SUCCESS
)
1113 /* couldn't decode DER */
1115 asn1_delete_structure (&dn
);
1116 return _gnutls_asn2err (result
);
1120 _gnutls_x509_parse_dn_oid (dn
, "rdnSequence", oid
, indx
,
1121 raw_flag
, buf
, sizeof_buf
);
1123 asn1_delete_structure (&dn
);
1129 * gnutls_x509_rdn_get_oid:
1130 * @idn: should contain a DER encoded RDN sequence
1131 * @indx: Indicates which OID to return. Use 0 for the first one.
1132 * @buf: a pointer to a structure to hold the peer's name OID
1133 * @sizeof_buf: holds the size of @buf
1135 * This function will return the specified Object identifier, of the
1138 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
1139 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
1140 * updated if the provided buffer is not long enough, otherwise a
1141 * negative error value.
1146 gnutls_x509_rdn_get_oid (const gnutls_datum_t
* idn
,
1147 int indx
, void *buf
, size_t * sizeof_buf
)
1150 ASN1_TYPE dn
= ASN1_TYPE_EMPTY
;
1152 if (sizeof_buf
== 0)
1154 return GNUTLS_E_INVALID_REQUEST
;
1158 asn1_create_element (_gnutls_get_pkix (),
1159 "PKIX1.Name", &dn
)) != ASN1_SUCCESS
)
1162 return _gnutls_asn2err (result
);
1165 result
= asn1_der_decoding (&dn
, idn
->data
, idn
->size
, NULL
);
1166 if (result
!= ASN1_SUCCESS
)
1168 /* couldn't decode DER */
1170 asn1_delete_structure (&dn
);
1171 return _gnutls_asn2err (result
);
1174 result
= _gnutls_x509_get_dn_oid (dn
, "rdnSequence", indx
, buf
, sizeof_buf
);
1176 asn1_delete_structure (&dn
);
1182 * Compares the DER encoded part of a DN.
1184 * FIXME: use a real DN comparison algorithm.
1186 * Returns 1 if the DN's match and (0) if they don't match. Otherwise
1187 * a negative error code is returned to indicate error.
1190 _gnutls_x509_compare_raw_dn (const gnutls_datum_t
* dn1
,
1191 const gnutls_datum_t
* dn2
)
1194 if (dn1
->size
!= dn2
->size
)
1199 if (memcmp (dn1
->data
, dn2
->data
, dn2
->size
) != 0)
1204 return 1; /* they match */
1208 * gnutls_x509_dn_export:
1209 * @dn: Holds the uint8_t DN object
1210 * @format: the format of output params. One of PEM or DER.
1211 * @output_data: will contain a DN PEM or DER encoded
1212 * @output_data_size: holds the size of output_data (and will be
1213 * replaced by the actual size of parameters)
1215 * This function will export the DN to DER or PEM format.
1217 * If the buffer provided is not long enough to hold the output, then
1218 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
1221 * If the structure is PEM encoded, it will have a header
1224 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1225 * negative error value.
1228 gnutls_x509_dn_export (gnutls_x509_dn_t dn
,
1229 gnutls_x509_crt_fmt_t format
, void *output_data
,
1230 size_t * output_data_size
)
1232 ASN1_TYPE asn1
= dn
;
1237 return GNUTLS_E_INVALID_REQUEST
;
1240 return _gnutls_x509_export_int_named (asn1
, "rdnSequence",
1242 output_data
, output_data_size
);
1246 * gnutls_x509_dn_export2:
1247 * @dn: Holds the uint8_t DN object
1248 * @format: the format of output params. One of PEM or DER.
1249 * @out: will contain a DN PEM or DER encoded
1251 * This function will export the DN to DER or PEM format.
1253 * The output buffer is allocated using gnutls_malloc().
1255 * If the structure is PEM encoded, it will have a header
1258 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1259 * negative error value.
1262 gnutls_x509_dn_export2 (gnutls_x509_dn_t dn
,
1263 gnutls_x509_crt_fmt_t format
, gnutls_datum_t
*out
)
1265 ASN1_TYPE asn1
= dn
;
1270 return GNUTLS_E_INVALID_REQUEST
;
1273 return _gnutls_x509_export_int_named2 (asn1
, "rdnSequence",
1274 format
, "NAME", out
);