1 /*
2  * Copyright (C) 2013-2016 Nikos Mavrogiannopoulos
3  * Copyright (C) 2016 Red Hat, Inc.
4  *
5  * This file is part of GnuTLS.
6  *
7  * The GnuTLS is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>
19  *
20  */
21 
22 /* This file contains functions to handle X.509 certificate generation.
23  */
24 
25 #include "gnutls_int.h"
26 
27 #include <datum.h>
28 #include <global.h>
29 #include "errors.h"
30 #include <common.h>
31 #include <x509.h>
32 #include <x509_b64.h>
33 #include <c-ctype.h>
34 
35 typedef int (*set_dn_func) (void *, const char *oid, unsigned int raw_flag,
36 			    const void *name, unsigned int name_size);
37 
38 static
dn_attr_crt_set(set_dn_func f,void * crt,const gnutls_datum_t * name,const gnutls_datum_t * val,unsigned is_raw)39 int dn_attr_crt_set(set_dn_func f, void *crt, const gnutls_datum_t * name,
40 		    const gnutls_datum_t * val, unsigned is_raw)
41 {
42 	char _oid[MAX_OID_SIZE];
43 	gnutls_datum_t tmp;
44 	const char *oid;
45 	int ret;
46 	unsigned i,j;
47 
48 	if (name->size == 0 || val->size == 0)
49 		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
50 
51 	if (c_isdigit(name->data[0]) != 0) {
52 		if (name->size >= sizeof(_oid))
53 			return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
54 
55 		memcpy(_oid, name->data, name->size);
56 		_oid[name->size] = 0;
57 
58 		oid = _oid;
59 
60 		if (gnutls_x509_dn_oid_known(oid) == 0 && !is_raw) {
61 			_gnutls_debug_log("Unknown OID: '%s'\n", oid);
62 			return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
63 		}
64 	} else {
65 		oid =
66 		    _gnutls_ldap_string_to_oid((char *) name->data,
67 					       name->size);
68 	}
69 
70 	if (oid == NULL) {
71 		_gnutls_debug_log("Unknown DN attribute: '%.*s'\n",
72 				  (int) name->size, name->data);
73 		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
74 	}
75 
76 	if (is_raw) {
77 		gnutls_datum_t hex = {val->data+1, val->size-1};
78 
79 		ret = gnutls_hex_decode2(&hex, &tmp);
80 		if (ret < 0)
81 			return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
82 	} else {
83 		tmp.size = val->size;
84 		tmp.data = gnutls_malloc(tmp.size+1);
85 		if (tmp.data == NULL) {
86 			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
87 		}
88 
89 		/* unescape */
90 		for (j=i=0;i<tmp.size;i++) {
91 			if (1+j!=val->size && val->data[j] == '\\') {
92 				if (val->data[j+1] == ',' || val->data[j+1] == '#' ||
93 				    val->data[j+1] == ' ' || val->data[j+1] == '+' ||
94 				    val->data[j+1] == '"' || val->data[j+1] == '<' ||
95 				    val->data[j+1] == '>' || val->data[j+1] == ';' ||
96 				    val->data[j+1] == '\\' || val->data[j+1] == '=') {
97 					tmp.data[i] = val->data[j+1];
98 					j+=2;
99 					tmp.size--;
100 				} else {
101 					ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
102 					goto fail;
103 				}
104 			} else {
105 				tmp.data[i] = val->data[j++];
106 			}
107 		}
108 		tmp.data[tmp.size] = 0;
109 	}
110 
111 	ret = f(crt, oid, is_raw, tmp.data, tmp.size);
112 	if (ret < 0) {
113 		gnutls_assert();
114 		goto fail;
115 	}
116 
117 	ret = 0;
118  fail:
119 	gnutls_free(tmp.data);
120 	return ret;
121 }
122 
read_attr_and_val(const char ** ptr,gnutls_datum_t * name,gnutls_datum_t * val,unsigned * is_raw)123 static int read_attr_and_val(const char **ptr,
124 			     gnutls_datum_t *name, gnutls_datum_t *val,
125 			     unsigned *is_raw)
126 {
127 	const unsigned char *p = (void *) *ptr;
128 
129 	*is_raw = 0;
130 
131 	/* skip any space */
132 	while (c_isspace(*p))
133 		p++;
134 
135 	/* Read the name */
136 	name->data = (void *) p;
137 	while (*p != '=' && *p != 0 && !c_isspace(*p))
138 		p++;
139 
140 	name->size = p - name->data;
141 
142 	/* skip any space */
143 	while (c_isspace(*p))
144 		p++;
145 
146 	if (*p != '=')
147 		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
148 	p++;
149 
150 	while (c_isspace(*p))
151 		p++;
152 
153 	if (*p == '#') {
154 		*is_raw = 1;
155 	}
156 
157 	/* Read value */
158 	val->data = (void *) p;
159 	while (*p != 0 && (*p != ',' || (*p == ',' && *(p - 1) == '\\'))
160 	       && *p != '\n') {
161 		p++;
162 	}
163 	val->size = p - (val->data);
164 	*ptr = (void*)p;
165 
166 	p = val->data;
167 	/* check for unescaped '+' - we do not support them */
168 	while (*p != 0) {
169 		if (*p == '+' && (*(p - 1) != '\\'))
170 			return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
171 		p++;
172 	}
173 
174 	/* remove spaces from the end */
175 	while(val->size > 0 && c_isspace(val->data[val->size-1])) {
176 		if (val->size-2 > 0 && val->data[val->size-2] == '\\')
177 			break;
178 		val->size--;
179 	}
180 
181 	if (val->size == 0 || name->size == 0)
182 		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
183 
184 	return 0;
185 }
186 
187 typedef struct elem_list_st {
188 	gnutls_datum_t name;
189 	gnutls_datum_t val;
190 	const char *pos;
191 	unsigned is_raw;
192 	struct elem_list_st *next;
193 } elem_list_st;
194 
add_new_elem(elem_list_st ** head,const gnutls_datum_t * name,const gnutls_datum_t * val,const char * pos,unsigned is_raw)195 static int add_new_elem(elem_list_st **head, const gnutls_datum_t *name, const gnutls_datum_t *val, const char *pos, unsigned is_raw)
196 {
197 	elem_list_st *elem = gnutls_malloc(sizeof(*elem));
198 	if (elem == NULL)
199 		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
200 
201 	memcpy(&elem->name, name, sizeof(*name));
202 	memcpy(&elem->val, val, sizeof(*val));
203 	elem->pos = pos;
204 	elem->is_raw = is_raw;
205 	elem->next = *head;
206 	*head = elem;
207 
208 	return 0;
209 }
210 
211 static int
crt_set_dn(set_dn_func f,void * crt,const char * dn,const char ** err)212 crt_set_dn(set_dn_func f, void *crt, const char *dn, const char **err)
213 {
214 	const char *p = dn;
215 	int ret;
216 	gnutls_datum_t name, val;
217 	unsigned is_raw;
218 	elem_list_st *list = NULL, *plist, *next;
219 
220 	if (crt == NULL || dn == NULL)
221 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
222 
223 	/* We parse the string and set all elements to a linked list in
224 	 * reverse order. That way we can encode in reverse order,
225 	 * the way RFC4514 requires. */
226 
227 	/* For each element */
228 	while (*p != 0 && *p != '\n') {
229 		if (err)
230 			*err = p;
231 
232 		is_raw = 0;
233 		ret = read_attr_and_val(&p, &name, &val, &is_raw);
234 		if (ret < 0) {
235 			gnutls_assert();
236 			goto fail;
237 		}
238 
239 		/* skip spaces and look for comma */
240 		while (c_isspace(*p))
241 			p++;
242 
243 		ret = add_new_elem(&list, &name, &val, p, is_raw);
244 		if (ret < 0) {
245 			gnutls_assert();
246 			goto fail;
247 		}
248 
249 		if (*p != ',' && *p != 0 && *p != '\n') {
250 			ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
251 			goto fail;
252 		}
253 		if (*p == ',')
254 			p++;
255 	}
256 
257 	plist = list;
258 	while(plist) {
259 		if (err)
260 			*err = plist->pos;
261 		ret = dn_attr_crt_set(f, crt, &plist->name, &plist->val, plist->is_raw);
262 		if (ret < 0)
263 			goto fail;
264 
265 		plist = plist->next;
266 	}
267 
268 	ret = 0;
269 fail:
270 	plist = list;
271 	while(plist) {
272 		next = plist->next;
273 		gnutls_free(plist);
274 		plist = next;
275 	}
276 	return ret;
277 }
278 
279 
280 /**
281  * gnutls_x509_crt_set_dn:
282  * @crt: a certificate of type #gnutls_x509_crt_t
283  * @dn: a comma separated DN string (RFC4514)
284  * @err: indicates the error position (if any)
285  *
286  * This function will set the DN on the provided certificate.
287  * The input string should be plain ASCII or UTF-8 encoded. On
288  * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
289  *
290  * Note that DNs are not expected to hold DNS information, and thus
291  * no automatic IDNA conversions are attempted when using this function.
292  * If that is required (e.g., store a domain in CN), process the corresponding
293  * input with gnutls_idna_map().
294  *
295  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
296  *   negative error value.
297  **/
298 int
gnutls_x509_crt_set_dn(gnutls_x509_crt_t crt,const char * dn,const char ** err)299 gnutls_x509_crt_set_dn(gnutls_x509_crt_t crt, const char *dn,
300 		       const char **err)
301 {
302 	return crt_set_dn((set_dn_func) gnutls_x509_crt_set_dn_by_oid, crt,
303 			  dn, err);
304 }
305 
306 /**
307  * gnutls_x509_crt_set_issuer_dn:
308  * @crt: a certificate of type #gnutls_x509_crt_t
309  * @dn: a comma separated DN string (RFC4514)
310  * @err: indicates the error position (if any)
311  *
312  * This function will set the DN on the provided certificate.
313  * The input string should be plain ASCII or UTF-8 encoded. On
314  * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
315  *
316  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
317  *   negative error value.
318  **/
319 int
gnutls_x509_crt_set_issuer_dn(gnutls_x509_crt_t crt,const char * dn,const char ** err)320 gnutls_x509_crt_set_issuer_dn(gnutls_x509_crt_t crt, const char *dn,
321 			      const char **err)
322 {
323 	return crt_set_dn((set_dn_func)
324 			  gnutls_x509_crt_set_issuer_dn_by_oid, crt, dn,
325 			  err);
326 }
327 
328 /**
329  * gnutls_x509_crq_set_dn:
330  * @crq: a certificate of type #gnutls_x509_crq_t
331  * @dn: a comma separated DN string (RFC4514)
332  * @err: indicates the error position (if any)
333  *
334  * This function will set the DN on the provided certificate.
335  * The input string should be plain ASCII or UTF-8 encoded. On
336  * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
337  *
338  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
339  *   negative error value.
340  **/
341 int
gnutls_x509_crq_set_dn(gnutls_x509_crq_t crq,const char * dn,const char ** err)342 gnutls_x509_crq_set_dn(gnutls_x509_crq_t crq, const char *dn,
343 		       const char **err)
344 {
345 	return crt_set_dn((set_dn_func) gnutls_x509_crq_set_dn_by_oid, crq,
346 			  dn, err);
347 }
348 
349 static
set_dn_by_oid(gnutls_x509_dn_t dn,const char * oid,unsigned int raw_flag,const void * name,unsigned name_size)350 int set_dn_by_oid(gnutls_x509_dn_t dn, const char *oid, unsigned int raw_flag, const void *name, unsigned name_size)
351 {
352 	return _gnutls_x509_set_dn_oid(dn->asn, "", oid, raw_flag, name, name_size);
353 }
354 
355 /**
356  * gnutls_x509_dn_set_str:
357  * @dn: a pointer to DN
358  * @str: a comma separated DN string (RFC4514)
359  * @err: indicates the error position (if any)
360  *
361  * This function will set the DN on the provided DN structure.
362  * The input string should be plain ASCII or UTF-8 encoded. On
363  * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
364  *
365  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
366  *   negative error value.
367  *
368  * Since: 3.5.3
369  **/
370 int
gnutls_x509_dn_set_str(gnutls_x509_dn_t dn,const char * str,const char ** err)371 gnutls_x509_dn_set_str(gnutls_x509_dn_t dn, const char *str, const char **err)
372 {
373 	if (dn == NULL) {
374 		gnutls_assert();
375 		return GNUTLS_E_INVALID_REQUEST;
376 	}
377 
378 	return crt_set_dn((set_dn_func) set_dn_by_oid, dn,
379 			  str, err);
380 }
381 
382 /**
383  * gnutls_x509_dn_init:
384  * @dn: the object to be initialized
385  *
386  * This function initializes a #gnutls_x509_dn_t type.
387  *
388  * The object returned must be deallocated using
389  * gnutls_x509_dn_deinit().
390  *
391  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
392  *   negative error value.
393  *
394  * Since: 2.4.0
395  **/
gnutls_x509_dn_init(gnutls_x509_dn_t * dn)396 int gnutls_x509_dn_init(gnutls_x509_dn_t * dn)
397 {
398 	int result;
399 
400 	*dn = gnutls_calloc(1, sizeof(gnutls_x509_dn_st));
401 
402 	if ((result =
403 	     asn1_create_element(_gnutls_get_pkix(),
404 				 "PKIX1.Name", &(*dn)->asn)) != ASN1_SUCCESS) {
405 		gnutls_assert();
406 		gnutls_free(*dn);
407 		return _gnutls_asn2err(result);
408 	}
409 
410 	return 0;
411 }
412 
413 /**
414  * gnutls_x509_dn_import:
415  * @dn: the structure that will hold the imported DN
416  * @data: should contain a DER encoded RDN sequence
417  *
418  * This function parses an RDN sequence and stores the result to a
419  * #gnutls_x509_dn_t type. The data must have been initialized
420  * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to
421  * decode the DN.
422  *
423  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
424  *   negative error value.
425  *
426  * Since: 2.4.0
427  **/
gnutls_x509_dn_import(gnutls_x509_dn_t dn,const gnutls_datum_t * data)428 int gnutls_x509_dn_import(gnutls_x509_dn_t dn, const gnutls_datum_t * data)
429 {
430 	int result;
431 	char err[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
432 
433 	if (data->data == NULL || data->size == 0)
434 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
435 
436 	result = _asn1_strict_der_decode(&dn->asn,
437 				   data->data, data->size, err);
438 	if (result != ASN1_SUCCESS) {
439 		/* couldn't decode DER */
440 		_gnutls_debug_log("ASN.1 Decoding error: %s\n", err);
441 		gnutls_assert();
442 		return _gnutls_asn2err(result);
443 	}
444 
445 	return 0;
446 }
447 
448 /**
449  * gnutls_x509_dn_deinit:
450  * @dn: a DN uint8_t object pointer.
451  *
452  * This function deallocates the DN object as returned by
453  * gnutls_x509_dn_import().
454  *
455  * Since: 2.4.0
456  **/
gnutls_x509_dn_deinit(gnutls_x509_dn_t dn)457 void gnutls_x509_dn_deinit(gnutls_x509_dn_t dn)
458 {
459 	asn1_delete_structure(&dn->asn);
460 	gnutls_free(dn);
461 }
462 
463 /**
464  * gnutls_x509_dn_export:
465  * @dn: Holds the uint8_t DN object
466  * @format: the format of output params. One of PEM or DER.
467  * @output_data: will contain a DN PEM or DER encoded
468  * @output_data_size: holds the size of output_data (and will be
469  *   replaced by the actual size of parameters)
470  *
471  * This function will export the DN to DER or PEM format.
472  *
473  * If the buffer provided is not long enough to hold the output, then
474  * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
475  * will be returned.
476  *
477  * If the structure is PEM encoded, it will have a header
478  * of "BEGIN NAME".
479  *
480  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
481  *   negative error value.
482  **/
483 int
gnutls_x509_dn_export(gnutls_x509_dn_t dn,gnutls_x509_crt_fmt_t format,void * output_data,size_t * output_data_size)484 gnutls_x509_dn_export(gnutls_x509_dn_t dn,
485 		      gnutls_x509_crt_fmt_t format, void *output_data,
486 		      size_t * output_data_size)
487 {
488 	if (dn == NULL) {
489 		gnutls_assert();
490 		return GNUTLS_E_INVALID_REQUEST;
491 	}
492 
493 	return _gnutls_x509_export_int_named(dn->asn, "rdnSequence",
494 					     format, "NAME",
495 					     output_data,
496 					     output_data_size);
497 }
498 
499 /**
500  * gnutls_x509_dn_export2:
501  * @dn: Holds the uint8_t DN object
502  * @format: the format of output params. One of PEM or DER.
503  * @out: will contain a DN PEM or DER encoded
504  *
505  * This function will export the DN to DER or PEM format.
506  *
507  * The output buffer is allocated using gnutls_malloc().
508  *
509  * If the structure is PEM encoded, it will have a header
510  * of "BEGIN NAME".
511  *
512  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
513  *   negative error value.
514  *
515  * Since: 3.1.3
516  **/
517 int
gnutls_x509_dn_export2(gnutls_x509_dn_t dn,gnutls_x509_crt_fmt_t format,gnutls_datum_t * out)518 gnutls_x509_dn_export2(gnutls_x509_dn_t dn,
519 		       gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
520 {
521 	if (dn == NULL) {
522 		gnutls_assert();
523 		return GNUTLS_E_INVALID_REQUEST;
524 	}
525 
526 	return _gnutls_x509_export_int_named2(dn->asn, "rdnSequence",
527 					      format, "NAME", out);
528 }
529 
530 /**
531  * gnutls_x509_dn_get_rdn_ava:
532  * @dn: a pointer to DN
533  * @irdn: index of RDN
534  * @iava: index of AVA.
535  * @ava: Pointer to structure which will hold output information.
536  *
537  * Get pointers to data within the DN. The format of the @ava structure
538  * is shown below.
539  *
540  *  struct gnutls_x509_ava_st {
541  *    gnutls_datum_t oid;
542  *    gnutls_datum_t value;
543  *    unsigned long value_tag;
544  *  };
545  *
546  * The X.509 distinguished name is a sequence of sequences of strings
547  * and this is what the @irdn and @iava indexes model.
548  *
549  * Note that @ava will contain pointers into the @dn structure which
550  * in turns points to the original certificate. Thus you should not
551  * modify any data or deallocate any of those.
552  *
553  * This is a low-level function that requires the caller to do the
554  * value conversions when necessary (e.g. from UCS-2).
555  *
556  * Returns: Returns 0 on success, or an error code.
557  **/
558 int
gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn,int irdn,int iava,gnutls_x509_ava_st * ava)559 gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn,
560 			   int irdn, int iava, gnutls_x509_ava_st * ava)
561 {
562 	ASN1_TYPE rdn, elem;
563 	ASN1_DATA_NODE vnode;
564 	long len;
565 	int lenlen, remlen, ret;
566 	char rbuf[MAX_NAME_SIZE];
567 	unsigned char cls;
568 	const unsigned char *ptr;
569 
570 	iava++;
571 	irdn++;			/* 0->1, 1->2 etc */
572 
573 	snprintf(rbuf, sizeof(rbuf), "rdnSequence.?%d.?%d", irdn, iava);
574 	rdn = asn1_find_node(dn->asn, rbuf);
575 	if (!rdn) {
576 		gnutls_assert();
577 		return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
578 	}
579 
580 	snprintf(rbuf, sizeof(rbuf), "?%d.type", iava);
581 	elem = asn1_find_node(rdn, rbuf);
582 	if (!elem) {
583 		gnutls_assert();
584 		return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
585 	}
586 
587 	ret = asn1_read_node_value(elem, &vnode);
588 	if (ret != ASN1_SUCCESS) {
589 		gnutls_assert();
590 		return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
591 	}
592 
593 	ava->oid.data = (void *) vnode.value;
594 	ava->oid.size = vnode.value_len;
595 
596 	snprintf(rbuf, sizeof(rbuf), "?%d.value", iava);
597 	elem = asn1_find_node(rdn, rbuf);
598 	if (!elem) {
599 		gnutls_assert();
600 		return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
601 	}
602 
603 	ret = asn1_read_node_value(elem, &vnode);
604 	if (ret != ASN1_SUCCESS) {
605 		gnutls_assert();
606 		return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
607 	}
608 	/* The value still has the previous tag's length bytes, plus the
609 	 * current value's tag and length bytes. Decode them.
610 	 */
611 
612 	ptr = vnode.value;
613 	remlen = vnode.value_len;
614 	len = asn1_get_length_der(ptr, remlen, &lenlen);
615 	if (len < 0) {
616 		gnutls_assert();
617 		return GNUTLS_E_ASN1_DER_ERROR;
618 	}
619 
620 	ptr += lenlen;
621 	remlen -= lenlen;
622 	ret =
623 	    asn1_get_tag_der(ptr, remlen, &cls, &lenlen, &ava->value_tag);
624 	if (ret) {
625 		gnutls_assert();
626 		return _gnutls_asn2err(ret);
627 	}
628 
629 	ptr += lenlen;
630 	remlen -= lenlen;
631 
632 	{
633 		signed long tmp;
634 
635 		tmp = asn1_get_length_der(ptr, remlen, &lenlen);
636 		if (tmp < 0) {
637 			gnutls_assert();
638 			return GNUTLS_E_ASN1_DER_ERROR;
639 		}
640 		ava->value.size = tmp;
641 	}
642 	ava->value.data = (void *) (ptr + lenlen);
643 
644 	return 0;
645 }
646 
647 /**
648  * gnutls_x509_dn_get_str:
649  * @dn: a pointer to DN
650  * @str: a datum that will hold the name
651  *
652  * This function will allocate buffer and copy the name in the provided DN.
653  * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
654  * described in RFC4514. The output string will be ASCII or UTF-8
655  * encoded, depending on the certificate data.
656  *
657  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
658  *   negative error value.
659  *
660  * Since: 3.4.2
661  **/
662 int
gnutls_x509_dn_get_str(gnutls_x509_dn_t dn,gnutls_datum_t * str)663 gnutls_x509_dn_get_str(gnutls_x509_dn_t dn, gnutls_datum_t *str)
664 {
665 	if (dn == NULL) {
666 		gnutls_assert();
667 		return GNUTLS_E_INVALID_REQUEST;
668 	}
669 
670 	return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str, GNUTLS_X509_DN_FLAG_COMPAT);
671 }
672 
673 /**
674  * gnutls_x509_dn_get_str:
675  * @dn: a pointer to DN
676  * @str: a datum that will hold the name
677  * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
678  *
679  * This function will allocate buffer and copy the name in the provided DN.
680  * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
681  * described in RFC4514. The output string will be ASCII or UTF-8
682  * encoded, depending on the certificate data.
683  *
684  * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
685  * format will match the format output by previous to 3.5.6 versions of GnuTLS
686  * which was not not fully RFC4514-compliant.
687  *
688  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
689  *   negative error value.
690  *
691  * Since: 3.5.7
692  **/
693 int
gnutls_x509_dn_get_str2(gnutls_x509_dn_t dn,gnutls_datum_t * str,unsigned flags)694 gnutls_x509_dn_get_str2(gnutls_x509_dn_t dn, gnutls_datum_t *str, unsigned flags)
695 {
696 	if (dn == NULL) {
697 		gnutls_assert();
698 		return GNUTLS_E_INVALID_REQUEST;
699 	}
700 
701 	return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str, flags);
702 }
703