Added functions to export structures in an allocated buffer.
[gnutls.git] / lib / x509 / dn.c
blob9c6096193de9cf662b88cb827ac78bcf49f0f267
1 /*
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>
24 #include <libtasn1.h>
25 #include <gnutls_datum.h>
26 #include <gnutls_global.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_str.h>
29 #include <common.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.
38 static char *
39 str_escape (char *str, char *buffer, unsigned int buffer_size)
41 int str_length, j, i;
43 if (str == NULL || buffer == NULL)
44 return 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] == '>'
52 || str[i] == ';')
53 buffer[j++] = '\\';
55 buffer[j++] = str[i];
58 /* null terminate the string */
59 buffer[j] = 0;
61 return buffer;
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.
70 int
71 _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct,
72 const char *asn1_rdn_name, char *buf,
73 size_t * sizeof_buf)
75 gnutls_buffer_st out_str;
76 int k2, k1, result;
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;
81 char *escaped = NULL;
82 const char *ldap_desc;
83 char oid[MAX_OID_SIZE];
84 int len, printable;
85 char *string = NULL;
86 size_t sizeof_string, sizeof_escaped;
88 if (sizeof_buf == NULL)
90 gnutls_assert ();
91 return GNUTLS_E_INVALID_REQUEST;
94 if (*sizeof_buf > 0 && buf)
95 buf[0] = 0;
96 else
97 *sizeof_buf = 0;
99 _gnutls_buffer_init (&out_str);
101 k1 = 0;
105 k1++;
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,
110 k1);
111 else
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)
119 break;
122 if (result != ASN1_VALUE_NOT_FOUND)
124 gnutls_assert ();
125 result = _gnutls_asn2err (result);
126 goto cleanup;
129 k2 = 0;
132 { /* Move to the attibute type and values
134 k2++;
136 if (tmpbuffer1[0] != 0)
137 snprintf (tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1,
138 k2);
139 else
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)
149 break;
150 if (result != ASN1_VALUE_NOT_FOUND)
152 gnutls_assert ();
153 result = _gnutls_asn2err (result);
154 goto cleanup;
157 /* Read the OID
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)
166 break;
167 else if (result != ASN1_SUCCESS)
169 gnutls_assert ();
170 result = _gnutls_asn2err (result);
171 goto cleanup;
174 /* Read the Value
176 _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
177 _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value");
179 len = 0;
180 result = asn1_read_value (asn1_struct, tmpbuffer3, NULL, &len);
181 if (result != ASN1_MEM_ERROR)
183 gnutls_assert ();
184 result = _gnutls_asn2err (result);
185 goto cleanup;
188 value2 = gnutls_malloc (len);
189 if (value2 == NULL)
191 gnutls_assert ();
192 result = GNUTLS_E_MEMORY_ERROR;
193 goto cleanup;
196 result = asn1_read_value (asn1_struct, tmpbuffer3, value2, &len);
198 if (result != ASN1_SUCCESS)
200 gnutls_assert ();
201 result = _gnutls_asn2err (result);
202 goto cleanup;
204 #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \
205 gnutls_assert(); \
206 goto cleanup; \
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)
214 * character.
216 if (k1 != 1)
217 { /* the first time do not append a comma */
218 if (k2 != 1)
219 { /* adjoining multi-value RDN */
220 STR_APPEND ("+");
222 else
224 STR_APPEND (",");
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);
235 if (escaped == NULL)
237 gnutls_assert ();
238 result = GNUTLS_E_MEMORY_ERROR;
239 goto cleanup;
242 sizeof_string = 2 * len + 2; /* in case it is not printable */
244 string = gnutls_malloc (sizeof_string);
245 if (string == NULL)
247 gnutls_assert ();
248 result = GNUTLS_E_MEMORY_ERROR;
249 goto cleanup;
252 STR_APPEND (ldap_desc);
253 STR_APPEND ("=");
254 result = 0;
256 if (printable)
257 result =
258 _gnutls_x509_oid_data2string (oid,
259 value2, len,
260 string, &sizeof_string);
262 if (!printable || result < 0)
263 result =
264 _gnutls_x509_data2hex (value2, len, string, &sizeof_string);
266 if (result < 0)
268 gnutls_assert ();
269 _gnutls_debug_log
270 ("Found OID: '%s' with value '%s'\n",
271 oid, _gnutls_bin2hex (value2, len, escaped, sizeof_escaped,
272 NULL));
273 goto cleanup;
275 STR_APPEND (str_escape (string, escaped, sizeof_escaped));
276 gnutls_free (string);
277 string = NULL;
279 gnutls_free (escaped);
280 escaped = NULL;
281 gnutls_free (value2);
282 value2 = NULL;
285 while (1);
288 while (1);
290 if (out_str.length >= (unsigned int) *sizeof_buf)
292 gnutls_assert ();
293 *sizeof_buf = out_str.length + 1;
294 result = GNUTLS_E_SHORT_MEMORY_BUFFER;
295 goto cleanup;
298 if (buf)
300 _gnutls_buffer_pop_data (&out_str, buf, sizeof_buf);
301 buf[*sizeof_buf] = 0;
303 else
304 *sizeof_buf = out_str.length;
306 result = 0;
308 cleanup:
309 gnutls_free (value2);
310 gnutls_free (string);
311 gnutls_free (escaped);
312 _gnutls_buffer_clear (&out_str);
313 return result;
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)
335 int k2, k1, result;
336 char tmpbuffer1[ASN1_MAX_NAME_SIZE];
337 char tmpbuffer2[ASN1_MAX_NAME_SIZE];
338 char tmpbuffer3[ASN1_MAX_NAME_SIZE];
339 uint8_t value[256];
340 char oid[MAX_OID_SIZE];
341 int len, printable;
342 int i = 0;
343 char *cbuf = buf;
345 if (cbuf == NULL)
346 *sizeof_buf = 0;
347 else
348 cbuf[0] = 0;
350 k1 = 0;
354 k1++;
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,
359 k1);
360 else
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)
368 gnutls_assert ();
369 break;
372 if (result != ASN1_VALUE_NOT_FOUND)
374 gnutls_assert ();
375 result = _gnutls_asn2err (result);
376 goto cleanup;
379 k2 = 0;
382 { /* Move to the attibute type and values
384 k2++;
386 if (tmpbuffer1[0] != 0)
387 snprintf (tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1,
388 k2);
389 else
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)
400 break;
402 if (result != ASN1_VALUE_NOT_FOUND)
404 gnutls_assert ();
405 result = _gnutls_asn2err (result);
406 goto cleanup;
409 /* Read the OID
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)
418 break;
419 else if (result != ASN1_SUCCESS)
421 gnutls_assert ();
422 result = _gnutls_asn2err (result);
423 goto cleanup;
426 if (strcmp (oid, given_oid) == 0 && indx == i++)
427 { /* Found the OID */
429 /* Read the Value
431 _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
432 _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value");
434 len = *sizeof_buf;
435 result = asn1_read_value (asn1_struct, tmpbuffer3, buf, &len);
437 if (result != ASN1_SUCCESS)
439 gnutls_assert ();
440 if (result == ASN1_MEM_ERROR)
441 *sizeof_buf = len;
442 result = _gnutls_asn2err (result);
443 goto cleanup;
446 if (raw_flag != 0)
448 if ((unsigned) len > *sizeof_buf)
450 *sizeof_buf = len;
451 result = GNUTLS_E_SHORT_MEMORY_BUFFER;
452 goto cleanup;
454 *sizeof_buf = len;
456 return 0;
459 else
460 { /* parse data. raw_flag == 0 */
461 printable = _gnutls_x509_oid_data_printable (oid);
463 if (printable == 1)
464 result =
465 _gnutls_x509_oid_data2string (oid, buf, len,
466 cbuf, sizeof_buf);
467 else
468 result =
469 _gnutls_x509_data2hex (buf, len, cbuf, sizeof_buf);
471 if (result < 0)
473 gnutls_assert ();
474 goto cleanup;
477 return 0;
479 } /* raw_flag == 0 */
482 while (1);
485 while (1);
487 gnutls_assert ();
489 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
491 cleanup:
492 return result;
496 /* Parses an X509 DN in the asn1_struct, and returns the requested
497 * DN OID.
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)
510 int k2, k1, result;
511 char tmpbuffer1[ASN1_MAX_NAME_SIZE];
512 char tmpbuffer2[ASN1_MAX_NAME_SIZE];
513 char tmpbuffer3[ASN1_MAX_NAME_SIZE];
514 char value[256];
515 char oid[MAX_OID_SIZE];
516 int len;
517 int i = 0;
519 k1 = 0;
523 k1++;
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,
528 k1);
529 else
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)
537 gnutls_assert ();
538 break;
541 if (result != ASN1_VALUE_NOT_FOUND)
543 gnutls_assert ();
544 result = _gnutls_asn2err (result);
545 goto cleanup;
548 k2 = 0;
551 { /* Move to the attibute type and values
553 k2++;
555 if (tmpbuffer1[0] != 0)
556 snprintf (tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1,
557 k2);
558 else
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)
569 break;
571 if (result != ASN1_VALUE_NOT_FOUND)
573 gnutls_assert ();
574 result = _gnutls_asn2err (result);
575 goto cleanup;
578 /* Read the OID
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)
587 break;
588 else if (result != ASN1_SUCCESS)
590 gnutls_assert ();
591 result = _gnutls_asn2err (result);
592 goto cleanup;
595 if (indx == i++)
596 { /* Found the OID */
598 len = strlen (oid) + 1;
600 if (*sizeof_oid < (unsigned) len)
602 *sizeof_oid = len;
603 gnutls_assert ();
604 return GNUTLS_E_SHORT_MEMORY_BUFFER;
607 memcpy (_oid, oid, len);
608 *sizeof_oid = len - 1;
610 return 0;
613 while (1);
616 while (1);
618 gnutls_assert ();
620 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
622 cleanup:
623 return result;
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,
633 const char *where,
634 const void *_data,
635 int sizeof_data, int multi)
637 const char *val_name;
638 const uint8_t *data = _data;
639 char tmp[128];
640 ASN1_TYPE c2;
641 int result;
644 /* Find how to encode the data.
646 val_name = _gnutls_x509_oid2asn_string (given_oid);
647 if (val_name == NULL)
649 gnutls_assert ();
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)
657 gnutls_assert ();
658 return _gnutls_asn2err (result);
661 tmp[0] = 0;
663 if ((result = _gnutls_x509_oid_data_choice (given_oid)) > 0)
665 const char *string_type;
666 int i;
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";
678 break;
682 /* if the type is a CHOICE then write the
683 * type we'll use.
685 result = asn1_write_value (c2, "", string_type, 1);
686 if (result != ASN1_SUCCESS)
688 gnutls_assert ();
689 result = _gnutls_asn2err (result);
690 goto error;
693 _gnutls_str_cpy (tmp, sizeof (tmp), string_type);
696 result = asn1_write_value (c2, tmp, data, sizeof_data);
697 if (result != ASN1_SUCCESS)
699 gnutls_assert ();
700 result = _gnutls_asn2err (result);
701 goto error;
705 /* write the data (value)
708 _gnutls_str_cpy (tmp, sizeof (tmp), where);
709 _gnutls_str_cat (tmp, sizeof (tmp), ".value");
711 if (multi != 0)
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)
718 gnutls_assert ();
719 result = _gnutls_asn2err (result);
720 goto error;
723 _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST");
727 result = _gnutls_x509_der_encode_and_copy (c2, "", asn1_struct, tmp, 0);
728 if (result < 0)
730 gnutls_assert ();
731 result = _gnutls_asn2err (result);
732 goto error;
735 /* write the type
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)
743 gnutls_assert ();
744 result = _gnutls_asn2err (result);
745 goto error;
748 result = 0;
750 error:
751 asn1_delete_structure (&c2);
752 return result;
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.
759 static int
760 _gnutls_x509_write_attribute (const char *given_oid,
761 ASN1_TYPE asn1_struct, const char *where,
762 const void *_data, int sizeof_data)
764 char tmp[128];
765 int result;
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);
774 if (result < 0)
776 gnutls_assert ();
777 return _gnutls_asn2err (result);
780 /* write the type
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)
788 gnutls_assert ();
789 return _gnutls_asn2err (result);
792 return 0;
796 /* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue
797 * otherwise.
799 * octet_string should be non (0) if we are to decode octet strings after
800 * decoding.
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)
810 char tmpbuffer[128];
811 int len, result;
813 /* Read the OID
815 _gnutls_str_cpy (tmpbuffer, sizeof (tmpbuffer), where);
816 _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), ".type");
818 len = oid_size - 1;
819 result = asn1_read_value (asn1_struct, tmpbuffer, oid, &len);
821 if (result != ASN1_SUCCESS)
823 gnutls_assert ();
824 result = _gnutls_asn2err (result);
825 return result;
828 /* Read the Value
831 _gnutls_str_cpy (tmpbuffer, sizeof (tmpbuffer), where);
832 _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), ".value");
834 if (multi)
835 _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), "s.?1"); /* .values.?1 */
837 result =
838 _gnutls_x509_read_value (asn1_struct, tmpbuffer, value, octet_string);
839 if (result < 0)
841 gnutls_assert ();
842 return result;
845 return 0;
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)
861 int result;
862 char tmp[ASN1_MAX_NAME_SIZE], asn1_rdn_name[ASN1_MAX_NAME_SIZE];
864 if (sizeof_name == 0 || name == NULL)
866 gnutls_assert ();
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)
875 gnutls_assert ();
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)
887 gnutls_assert ();
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)
899 gnutls_assert ();
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");
909 if (!raw_flag)
911 result =
912 _gnutls_x509_encode_and_write_attribute (given_oid,
913 asn1_struct,
914 tmp, name, sizeof_name, 0);
916 else
918 result =
919 _gnutls_x509_write_attribute (given_oid, asn1_struct,
920 tmp, name, sizeof_name);
923 if (result < 0)
925 gnutls_assert ();
926 return result;
929 return 0;
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.
944 * Since: 2.4.0
947 gnutls_x509_dn_init (gnutls_x509_dn_t * dn)
949 int result;
950 ASN1_TYPE tmpdn = ASN1_TYPE_EMPTY;
952 if ((result =
953 asn1_create_element (_gnutls_get_pkix (),
954 "PKIX1.Name", &tmpdn)) != ASN1_SUCCESS)
956 gnutls_assert ();
957 return _gnutls_asn2err (result);
960 *dn = tmpdn;
962 return 0;
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
973 * decode the DN.
975 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
976 * negative error value.
978 * Since: 2.4.0
981 gnutls_x509_dn_import (gnutls_x509_dn_t dn, const gnutls_datum_t * data)
983 int result;
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);
992 gnutls_assert ();
993 return _gnutls_asn2err (result);
996 return 0;
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().
1006 * Since: 2.4.0
1008 void
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
1022 * RFC4514.
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)
1033 int result;
1034 ASN1_TYPE dn = ASN1_TYPE_EMPTY;
1036 if (sizeof_buf == 0)
1038 gnutls_assert ();
1039 return GNUTLS_E_INVALID_REQUEST;
1042 if (buf)
1043 buf[0] = 0;
1046 if ((result =
1047 asn1_create_element (_gnutls_get_pkix (),
1048 "PKIX1.Name", &dn)) != ASN1_SUCCESS)
1050 gnutls_assert ();
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 */
1058 gnutls_assert ();
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);
1066 return result;
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
1082 * from RFC4514.
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)
1094 int result;
1095 ASN1_TYPE dn = ASN1_TYPE_EMPTY;
1097 if (sizeof_buf == 0)
1099 return GNUTLS_E_INVALID_REQUEST;
1102 if ((result =
1103 asn1_create_element (_gnutls_get_pkix (),
1104 "PKIX1.Name", &dn)) != ASN1_SUCCESS)
1106 gnutls_assert ();
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 */
1114 gnutls_assert ();
1115 asn1_delete_structure (&dn);
1116 return _gnutls_asn2err (result);
1119 result =
1120 _gnutls_x509_parse_dn_oid (dn, "rdnSequence", oid, indx,
1121 raw_flag, buf, sizeof_buf);
1123 asn1_delete_structure (&dn);
1124 return result;
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
1136 * RDN sequence.
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.
1143 * Since: 2.4.0
1146 gnutls_x509_rdn_get_oid (const gnutls_datum_t * idn,
1147 int indx, void *buf, size_t * sizeof_buf)
1149 int result;
1150 ASN1_TYPE dn = ASN1_TYPE_EMPTY;
1152 if (sizeof_buf == 0)
1154 return GNUTLS_E_INVALID_REQUEST;
1157 if ((result =
1158 asn1_create_element (_gnutls_get_pkix (),
1159 "PKIX1.Name", &dn)) != ASN1_SUCCESS)
1161 gnutls_assert ();
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 */
1169 gnutls_assert ();
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);
1177 return result;
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)
1196 gnutls_assert ();
1197 return 0;
1199 if (memcmp (dn1->data, dn2->data, dn2->size) != 0)
1201 gnutls_assert ();
1202 return 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
1219 * will be returned.
1221 * If the structure is PEM encoded, it will have a header
1222 * of "BEGIN NAME".
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;
1234 if (asn1 == NULL)
1236 gnutls_assert ();
1237 return GNUTLS_E_INVALID_REQUEST;
1240 return _gnutls_x509_export_int_named (asn1, "rdnSequence",
1241 format, "NAME",
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
1256 * of "BEGIN NAME".
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;
1267 if (asn1 == NULL)
1269 gnutls_assert ();
1270 return GNUTLS_E_INVALID_REQUEST;
1273 return _gnutls_x509_export_int_named2 (asn1, "rdnSequence",
1274 format, "NAME", out);