Added gnutls_x509_crt_set_policy()
[gnutls.git] / lib / x509 / dn.c
blob238e28ed86f7f35ba515e290ffa45a51590b5636
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 static int is_printable(char p)
628 if ((p >= 'a' && p <= 'z') || (p >= 'A' && p <= 'Z') ||
629 (p >= '0' && p <= '9') || p == ' ' || p == '(' || p == ')' ||
630 p == '(' || p == '+' || p == ',' || p == '-' || p == '.' ||
631 p == '/' || p == ':' || p == '=' || p == '?')
632 return 1;
634 return 0;
637 /* This will encode and write the AttributeTypeAndValue field.
638 * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute.
639 * In all cases only one value is written.
642 _gnutls_x509_encode_and_write_attribute (const char *given_oid,
643 ASN1_TYPE asn1_struct,
644 const char *where,
645 const void *_data,
646 int sizeof_data, int multi)
648 const char *val_name;
649 const uint8_t *data = _data;
650 char tmp[128];
651 ASN1_TYPE c2;
652 int result;
655 /* Find how to encode the data.
657 val_name = _gnutls_x509_oid2asn_string (given_oid);
658 if (val_name == NULL)
660 gnutls_assert ();
661 _gnutls_debug_log ("Cannot find OID: %s\n", given_oid);
662 return GNUTLS_E_X509_UNSUPPORTED_OID;
665 result = asn1_create_element (_gnutls_get_pkix (), val_name, &c2);
666 if (result != ASN1_SUCCESS)
668 gnutls_assert ();
669 return _gnutls_asn2err (result);
672 tmp[0] = 0;
674 if ((result = _gnutls_x509_oid_data_choice (given_oid)) > 0)
676 const char *string_type;
677 int i;
679 string_type = "printableString";
681 /* Check if the data is ASN.1 printable, and use
682 * the UTF8 string type if not.
684 for (i = 0; i < sizeof_data; i++)
686 if (!is_printable (data[i]))
688 string_type = "utf8String";
689 break;
693 /* if the type is a CHOICE then write the
694 * type we'll use.
696 result = asn1_write_value (c2, "", string_type, 1);
697 if (result != ASN1_SUCCESS)
699 gnutls_assert ();
700 result = _gnutls_asn2err (result);
701 goto error;
704 _gnutls_str_cpy (tmp, sizeof (tmp), string_type);
707 result = asn1_write_value (c2, tmp, data, sizeof_data);
708 if (result != ASN1_SUCCESS)
710 gnutls_assert ();
711 result = _gnutls_asn2err (result);
712 goto error;
716 /* write the data (value)
719 _gnutls_str_cpy (tmp, sizeof (tmp), where);
720 _gnutls_str_cat (tmp, sizeof (tmp), ".value");
722 if (multi != 0)
723 { /* if not writing an AttributeTypeAndValue, but an Attribute */
724 _gnutls_str_cat (tmp, sizeof (tmp), "s"); /* values */
726 result = asn1_write_value (asn1_struct, tmp, "NEW", 1);
727 if (result != ASN1_SUCCESS)
729 gnutls_assert ();
730 result = _gnutls_asn2err (result);
731 goto error;
734 _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST");
738 result = _gnutls_x509_der_encode_and_copy (c2, "", asn1_struct, tmp, 0);
739 if (result < 0)
741 gnutls_assert ();
742 result = _gnutls_asn2err (result);
743 goto error;
746 /* write the type
748 _gnutls_str_cpy (tmp, sizeof (tmp), where);
749 _gnutls_str_cat (tmp, sizeof (tmp), ".type");
751 result = asn1_write_value (asn1_struct, tmp, given_oid, 1);
752 if (result != ASN1_SUCCESS)
754 gnutls_assert ();
755 result = _gnutls_asn2err (result);
756 goto error;
759 result = 0;
761 error:
762 asn1_delete_structure (&c2);
763 return result;
766 /* This will write the AttributeTypeAndValue field. The data must be already DER encoded.
767 * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute.
768 * In all cases only one value is written.
770 static int
771 _gnutls_x509_write_attribute (const char *given_oid,
772 ASN1_TYPE asn1_struct, const char *where,
773 const void *_data, int sizeof_data)
775 char tmp[128];
776 int result;
778 /* write the data (value)
781 _gnutls_str_cpy (tmp, sizeof (tmp), where);
782 _gnutls_str_cat (tmp, sizeof (tmp), ".value");
784 result = asn1_write_value (asn1_struct, tmp, _data, sizeof_data);
785 if (result < 0)
787 gnutls_assert ();
788 return _gnutls_asn2err (result);
791 /* write the type
793 _gnutls_str_cpy (tmp, sizeof (tmp), where);
794 _gnutls_str_cat (tmp, sizeof (tmp), ".type");
796 result = asn1_write_value (asn1_struct, tmp, given_oid, 1);
797 if (result != ASN1_SUCCESS)
799 gnutls_assert ();
800 return _gnutls_asn2err (result);
803 return 0;
807 /* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue
808 * otherwise.
810 * octet_string should be non-zero if we are to decode octet strings after
811 * decoding.
813 * The output is allocated and stored in value.
816 _gnutls_x509_decode_and_read_attribute (ASN1_TYPE asn1_struct,
817 const char *where, char *oid,
818 int oid_size, gnutls_datum_t * value,
819 int multi, int octet_string)
821 char tmpbuffer[128];
822 int len, result;
824 /* Read the OID
826 _gnutls_str_cpy (tmpbuffer, sizeof (tmpbuffer), where);
827 _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), ".type");
829 len = oid_size - 1;
830 result = asn1_read_value (asn1_struct, tmpbuffer, oid, &len);
832 if (result != ASN1_SUCCESS)
834 gnutls_assert ();
835 result = _gnutls_asn2err (result);
836 return result;
839 /* Read the Value
842 _gnutls_str_cpy (tmpbuffer, sizeof (tmpbuffer), where);
843 _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), ".value");
845 if (multi)
846 _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), "s.?1"); /* .values.?1 */
848 if (octet_string)
849 result = _gnutls_x509_read_string (asn1_struct, tmpbuffer, value, RV_OCTET_STRING);
850 else
851 result = _gnutls_x509_read_value (asn1_struct, tmpbuffer, value);
852 if (result < 0)
854 gnutls_assert ();
855 return result;
858 return 0;
862 /* Sets an X509 DN in the asn1_struct, and puts the given OID in the DN.
863 * The input is assumed to be raw data.
865 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer".
866 * That is to point before the rndSequence.
870 _gnutls_x509_set_dn_oid (ASN1_TYPE asn1_struct,
871 const char *asn1_name, const char *given_oid,
872 int raw_flag, const char *name, int sizeof_name)
874 int result;
875 char tmp[ASN1_MAX_NAME_SIZE], asn1_rdn_name[ASN1_MAX_NAME_SIZE];
877 if (sizeof_name == 0 || name == NULL)
879 gnutls_assert ();
880 return GNUTLS_E_INVALID_REQUEST;
883 /* create the rdnSequence
885 result = asn1_write_value (asn1_struct, asn1_name, "rdnSequence", 1);
886 if (result != ASN1_SUCCESS)
888 gnutls_assert ();
889 return _gnutls_asn2err (result);
892 _gnutls_str_cpy (asn1_rdn_name, sizeof (asn1_rdn_name), asn1_name);
893 _gnutls_str_cat (asn1_rdn_name, sizeof (asn1_rdn_name), ".rdnSequence");
895 /* create a new element
897 result = asn1_write_value (asn1_struct, asn1_rdn_name, "NEW", 1);
898 if (result != ASN1_SUCCESS)
900 gnutls_assert ();
901 return _gnutls_asn2err (result);
904 _gnutls_str_cpy (tmp, sizeof (tmp), asn1_rdn_name);
905 _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST");
907 /* create the set with only one element
909 result = asn1_write_value (asn1_struct, tmp, "NEW", 1);
910 if (result != ASN1_SUCCESS)
912 gnutls_assert ();
913 return _gnutls_asn2err (result);
917 /* Encode and write the data
919 _gnutls_str_cpy (tmp, sizeof (tmp), asn1_rdn_name);
920 _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST.?LAST");
922 if (!raw_flag)
924 result =
925 _gnutls_x509_encode_and_write_attribute (given_oid,
926 asn1_struct,
927 tmp, name, sizeof_name, 0);
929 else
931 result =
932 _gnutls_x509_write_attribute (given_oid, asn1_struct,
933 tmp, name, sizeof_name);
936 if (result < 0)
938 gnutls_assert ();
939 return result;
942 return 0;
946 * gnutls_x509_dn_init:
947 * @dn: the object to be initialized
949 * This function initializes a #gnutls_x509_dn_t structure.
951 * The object returned must be deallocated using
952 * gnutls_x509_dn_deinit().
954 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
955 * negative error value.
957 * Since: 2.4.0
960 gnutls_x509_dn_init (gnutls_x509_dn_t * dn)
962 int result;
963 ASN1_TYPE tmpdn = ASN1_TYPE_EMPTY;
965 if ((result =
966 asn1_create_element (_gnutls_get_pkix (),
967 "PKIX1.Name", &tmpdn)) != ASN1_SUCCESS)
969 gnutls_assert ();
970 return _gnutls_asn2err (result);
973 *dn = tmpdn;
975 return 0;
979 * gnutls_x509_dn_import:
980 * @dn: the structure that will hold the imported DN
981 * @data: should contain a DER encoded RDN sequence
983 * This function parses an RDN sequence and stores the result to a
984 * #gnutls_x509_dn_t structure. The structure must have been initialized
985 * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to
986 * decode the DN.
988 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
989 * negative error value.
991 * Since: 2.4.0
994 gnutls_x509_dn_import (gnutls_x509_dn_t dn, const gnutls_datum_t * data)
996 int result;
997 char err[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
999 result = asn1_der_decoding ((ASN1_TYPE *) & dn,
1000 data->data, data->size, err);
1001 if (result != ASN1_SUCCESS)
1003 /* couldn't decode DER */
1004 _gnutls_debug_log ("ASN.1 Decoding error: %s\n", err);
1005 gnutls_assert ();
1006 return _gnutls_asn2err (result);
1009 return 0;
1013 * gnutls_x509_dn_deinit:
1014 * @dn: a DN uint8_t object pointer.
1016 * This function deallocates the DN object as returned by
1017 * gnutls_x509_dn_import().
1019 * Since: 2.4.0
1021 void
1022 gnutls_x509_dn_deinit (gnutls_x509_dn_t dn)
1024 asn1_delete_structure ((ASN1_TYPE *) & dn);
1028 * gnutls_x509_rdn_get:
1029 * @idn: should contain a DER encoded RDN sequence
1030 * @buf: a pointer to a structure to hold the peer's name
1031 * @sizeof_buf: holds the size of @buf
1033 * This function will return the name of the given RDN sequence. The
1034 * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in
1035 * RFC4514.
1037 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
1038 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
1039 * updated if the provided buffer is not long enough, otherwise a
1040 * negative error value.
1043 gnutls_x509_rdn_get (const gnutls_datum_t * idn,
1044 char *buf, size_t * sizeof_buf)
1046 int result;
1047 ASN1_TYPE dn = ASN1_TYPE_EMPTY;
1049 if (sizeof_buf == 0)
1051 gnutls_assert ();
1052 return GNUTLS_E_INVALID_REQUEST;
1055 if (buf)
1056 buf[0] = 0;
1059 if ((result =
1060 asn1_create_element (_gnutls_get_pkix (),
1061 "PKIX1.Name", &dn)) != ASN1_SUCCESS)
1063 gnutls_assert ();
1064 return _gnutls_asn2err (result);
1067 result = asn1_der_decoding (&dn, idn->data, idn->size, NULL);
1068 if (result != ASN1_SUCCESS)
1070 /* couldn't decode DER */
1071 gnutls_assert ();
1072 asn1_delete_structure (&dn);
1073 return _gnutls_asn2err (result);
1076 result = _gnutls_x509_parse_dn (dn, "rdnSequence", buf, sizeof_buf);
1078 asn1_delete_structure (&dn);
1079 return result;
1084 * gnutls_x509_rdn_get_by_oid:
1085 * @idn: should contain a DER encoded RDN sequence
1086 * @oid: an Object Identifier
1087 * @indx: In case multiple same OIDs exist in the RDN indicates which
1088 * to send. Use 0 for the first one.
1089 * @raw_flag: If non-zero then the raw DER data are returned.
1090 * @buf: a pointer to a structure to hold the peer's name
1091 * @sizeof_buf: holds the size of @buf
1093 * This function will return the name of the given Object identifier,
1094 * of the RDN sequence. The name will be encoded using the rules
1095 * from RFC4514.
1097 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
1098 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
1099 * updated if the provided buffer is not long enough, otherwise a
1100 * negative error value.
1103 gnutls_x509_rdn_get_by_oid (const gnutls_datum_t * idn, const char *oid,
1104 int indx, unsigned int raw_flag,
1105 void *buf, size_t * sizeof_buf)
1107 int result;
1108 ASN1_TYPE dn = ASN1_TYPE_EMPTY;
1110 if (sizeof_buf == 0)
1112 return GNUTLS_E_INVALID_REQUEST;
1115 if ((result =
1116 asn1_create_element (_gnutls_get_pkix (),
1117 "PKIX1.Name", &dn)) != ASN1_SUCCESS)
1119 gnutls_assert ();
1120 return _gnutls_asn2err (result);
1123 result = asn1_der_decoding (&dn, idn->data, idn->size, NULL);
1124 if (result != ASN1_SUCCESS)
1126 /* couldn't decode DER */
1127 gnutls_assert ();
1128 asn1_delete_structure (&dn);
1129 return _gnutls_asn2err (result);
1132 result =
1133 _gnutls_x509_parse_dn_oid (dn, "rdnSequence", oid, indx,
1134 raw_flag, buf, sizeof_buf);
1136 asn1_delete_structure (&dn);
1137 return result;
1142 * gnutls_x509_rdn_get_oid:
1143 * @idn: should contain a DER encoded RDN sequence
1144 * @indx: Indicates which OID to return. Use 0 for the first one.
1145 * @buf: a pointer to a structure to hold the peer's name OID
1146 * @sizeof_buf: holds the size of @buf
1148 * This function will return the specified Object identifier, of the
1149 * RDN sequence.
1151 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
1152 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
1153 * updated if the provided buffer is not long enough, otherwise a
1154 * negative error value.
1156 * Since: 2.4.0
1159 gnutls_x509_rdn_get_oid (const gnutls_datum_t * idn,
1160 int indx, void *buf, size_t * sizeof_buf)
1162 int result;
1163 ASN1_TYPE dn = ASN1_TYPE_EMPTY;
1165 if (sizeof_buf == 0)
1167 return GNUTLS_E_INVALID_REQUEST;
1170 if ((result =
1171 asn1_create_element (_gnutls_get_pkix (),
1172 "PKIX1.Name", &dn)) != ASN1_SUCCESS)
1174 gnutls_assert ();
1175 return _gnutls_asn2err (result);
1178 result = asn1_der_decoding (&dn, idn->data, idn->size, NULL);
1179 if (result != ASN1_SUCCESS)
1181 /* couldn't decode DER */
1182 gnutls_assert ();
1183 asn1_delete_structure (&dn);
1184 return _gnutls_asn2err (result);
1187 result = _gnutls_x509_get_dn_oid (dn, "rdnSequence", indx, buf, sizeof_buf);
1189 asn1_delete_structure (&dn);
1190 return result;
1195 * Compares the DER encoded part of a DN.
1197 * FIXME: use a real DN comparison algorithm.
1199 * Returns 1 if the DN's match and (0) if they don't match. Otherwise
1200 * a negative error code is returned to indicate error.
1203 _gnutls_x509_compare_raw_dn (const gnutls_datum_t * dn1,
1204 const gnutls_datum_t * dn2)
1207 if (dn1->size != dn2->size)
1209 gnutls_assert ();
1210 return 0;
1212 if (memcmp (dn1->data, dn2->data, dn2->size) != 0)
1214 gnutls_assert ();
1215 return 0;
1217 return 1; /* they match */
1221 * gnutls_x509_dn_export:
1222 * @dn: Holds the uint8_t DN object
1223 * @format: the format of output params. One of PEM or DER.
1224 * @output_data: will contain a DN PEM or DER encoded
1225 * @output_data_size: holds the size of output_data (and will be
1226 * replaced by the actual size of parameters)
1228 * This function will export the DN to DER or PEM format.
1230 * If the buffer provided is not long enough to hold the output, then
1231 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
1232 * will be returned.
1234 * If the structure is PEM encoded, it will have a header
1235 * of "BEGIN NAME".
1237 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1238 * negative error value.
1241 gnutls_x509_dn_export (gnutls_x509_dn_t dn,
1242 gnutls_x509_crt_fmt_t format, void *output_data,
1243 size_t * output_data_size)
1245 ASN1_TYPE asn1 = dn;
1247 if (asn1 == NULL)
1249 gnutls_assert ();
1250 return GNUTLS_E_INVALID_REQUEST;
1253 return _gnutls_x509_export_int_named (asn1, "rdnSequence",
1254 format, "NAME",
1255 output_data, output_data_size);
1259 * gnutls_x509_dn_export2:
1260 * @dn: Holds the uint8_t DN object
1261 * @format: the format of output params. One of PEM or DER.
1262 * @out: will contain a DN PEM or DER encoded
1264 * This function will export the DN to DER or PEM format.
1266 * The output buffer is allocated using gnutls_malloc().
1268 * If the structure is PEM encoded, it will have a header
1269 * of "BEGIN NAME".
1271 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1272 * negative error value.
1275 gnutls_x509_dn_export2 (gnutls_x509_dn_t dn,
1276 gnutls_x509_crt_fmt_t format, gnutls_datum_t *out)
1278 ASN1_TYPE asn1 = dn;
1280 if (asn1 == NULL)
1282 gnutls_assert ();
1283 return GNUTLS_E_INVALID_REQUEST;
1286 return _gnutls_x509_export_int_named2 (asn1, "rdnSequence",
1287 format, "NAME", out);