xref: /dragonfly/crypto/libressl/crypto/asn1/x_name.c (revision f9993810)
1 /* $OpenBSD: x_name.c,v 1.37 2021/12/25 13:17:48 jsing Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <ctype.h>
60 #include <stdio.h>
61 #include <string.h>
62 
63 #include <openssl/asn1t.h>
64 #include <openssl/err.h>
65 #include <openssl/x509.h>
66 
67 #include "asn1_locl.h"
68 #include "x509_lcl.h"
69 
70 typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
71 DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
72 
73 static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
74     long len, const ASN1_ITEM *it, int tag, int aclass, char opt,
75     ASN1_TLC *ctx);
76 
77 static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
78     const ASN1_ITEM *it, int tag, int aclass);
79 static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it);
80 static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
81 
82 static int x509_name_encode(X509_NAME *a);
83 static int x509_name_canon(X509_NAME *a);
84 static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in);
85 static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname,
86     unsigned char **in);
87 
88 static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, int indent,
89     const char *fname, const ASN1_PCTX *pctx);
90 
91 static const ASN1_TEMPLATE X509_NAME_ENTRY_seq_tt[] = {
92 	{
93 		.offset = offsetof(X509_NAME_ENTRY, object),
94 		.field_name = "object",
95 		.item = &ASN1_OBJECT_it,
96 	},
97 	{
98 		.offset = offsetof(X509_NAME_ENTRY, value),
99 		.field_name = "value",
100 		.item = &ASN1_PRINTABLE_it,
101 	},
102 };
103 
104 const ASN1_ITEM X509_NAME_ENTRY_it = {
105 	.itype = ASN1_ITYPE_SEQUENCE,
106 	.utype = V_ASN1_SEQUENCE,
107 	.templates = X509_NAME_ENTRY_seq_tt,
108 	.tcount = sizeof(X509_NAME_ENTRY_seq_tt) / sizeof(ASN1_TEMPLATE),
109 	.size = sizeof(X509_NAME_ENTRY),
110 	.sname = "X509_NAME_ENTRY",
111 };
112 
113 
114 X509_NAME_ENTRY *
115 d2i_X509_NAME_ENTRY(X509_NAME_ENTRY **a, const unsigned char **in, long len)
116 {
117 	return (X509_NAME_ENTRY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
118 	    &X509_NAME_ENTRY_it);
119 }
120 
121 int
122 i2d_X509_NAME_ENTRY(X509_NAME_ENTRY *a, unsigned char **out)
123 {
124 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_NAME_ENTRY_it);
125 }
126 
127 X509_NAME_ENTRY *
128 X509_NAME_ENTRY_new(void)
129 {
130 	return (X509_NAME_ENTRY *)ASN1_item_new(&X509_NAME_ENTRY_it);
131 }
132 
133 void
134 X509_NAME_ENTRY_free(X509_NAME_ENTRY *a)
135 {
136 	ASN1_item_free((ASN1_VALUE *)a, &X509_NAME_ENTRY_it);
137 }
138 
139 X509_NAME_ENTRY *
140 X509_NAME_ENTRY_dup(X509_NAME_ENTRY *x)
141 {
142 	return ASN1_item_dup(&X509_NAME_ENTRY_it, x);
143 }
144 
145 /* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY }
146  * so declare two template wrappers for this
147  */
148 
149 static const ASN1_TEMPLATE X509_NAME_ENTRIES_item_tt = {
150 	.flags = ASN1_TFLG_SET_OF,
151 	.tag = 0,
152 	.offset = 0,
153 	.field_name = "RDNS",
154 	.item = &X509_NAME_ENTRY_it,
155 };
156 
157 const ASN1_ITEM X509_NAME_ENTRIES_it = {
158 	.itype = ASN1_ITYPE_PRIMITIVE,
159 	.utype = -1,
160 	.templates = &X509_NAME_ENTRIES_item_tt,
161 	.tcount = 0,
162 	.funcs = NULL,
163 	.size = 0,
164 	.sname = "X509_NAME_ENTRIES",
165 };
166 
167 static const ASN1_TEMPLATE X509_NAME_INTERNAL_item_tt = {
168 	.flags = ASN1_TFLG_SEQUENCE_OF,
169 	.tag = 0,
170 	.offset = 0,
171 	.field_name = "Name",
172 	.item = &X509_NAME_ENTRIES_it,
173 };
174 
175 const ASN1_ITEM X509_NAME_INTERNAL_it = {
176 	.itype = ASN1_ITYPE_PRIMITIVE,
177 	.utype = -1,
178 	.templates = &X509_NAME_INTERNAL_item_tt,
179 	.tcount = 0,
180 	.funcs = NULL,
181 	.size = 0,
182 	.sname = "X509_NAME_INTERNAL",
183 };
184 
185 /* Normally that's where it would end: we'd have two nested STACK structures
186  * representing the ASN1. Unfortunately X509_NAME uses a completely different
187  * form and caches encodings so we have to process the internal form and convert
188  * to the external form.
189  */
190 
191 const ASN1_EXTERN_FUNCS x509_name_ff = {
192 	NULL,
193 	x509_name_ex_new,
194 	x509_name_ex_free,
195 	0,	/* Default clear behaviour is OK */
196 	x509_name_ex_d2i,
197 	x509_name_ex_i2d,
198 	x509_name_ex_print
199 };
200 
201 const ASN1_ITEM X509_NAME_it = {
202 	.itype = ASN1_ITYPE_EXTERN,
203 	.utype = V_ASN1_SEQUENCE,
204 	.templates = NULL,
205 	.tcount = 0,
206 	.funcs = &x509_name_ff,
207 	.size = 0,
208 	.sname = "X509_NAME",
209 };
210 
211 X509_NAME *
212 d2i_X509_NAME(X509_NAME **a, const unsigned char **in, long len)
213 {
214 	return (X509_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
215 	    &X509_NAME_it);
216 }
217 
218 int
219 i2d_X509_NAME(X509_NAME *a, unsigned char **out)
220 {
221 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_NAME_it);
222 }
223 
224 X509_NAME *
225 X509_NAME_new(void)
226 {
227 	return (X509_NAME *)ASN1_item_new(&X509_NAME_it);
228 }
229 
230 void
231 X509_NAME_free(X509_NAME *a)
232 {
233 	ASN1_item_free((ASN1_VALUE *)a, &X509_NAME_it);
234 }
235 
236 X509_NAME *
237 X509_NAME_dup(X509_NAME *x)
238 {
239 	return ASN1_item_dup(&X509_NAME_it, x);
240 }
241 
242 static int
243 x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
244 {
245 	X509_NAME *ret = NULL;
246 
247 	ret = malloc(sizeof(X509_NAME));
248 	if (!ret)
249 		goto memerr;
250 	if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL)
251 		goto memerr;
252 	if ((ret->bytes = BUF_MEM_new()) == NULL)
253 		goto memerr;
254 	ret->canon_enc = NULL;
255 	ret->canon_enclen = 0;
256 	ret->modified = 1;
257 	*val = (ASN1_VALUE *)ret;
258 	return 1;
259 
260  memerr:
261 	ASN1error(ERR_R_MALLOC_FAILURE);
262 	if (ret) {
263 		if (ret->entries)
264 			sk_X509_NAME_ENTRY_free(ret->entries);
265 		free(ret);
266 	}
267 	return 0;
268 }
269 
270 static void
271 x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
272 {
273 	X509_NAME *a;
274 
275 	if (!pval || !*pval)
276 		return;
277 	a = (X509_NAME *)*pval;
278 
279 	BUF_MEM_free(a->bytes);
280 	sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free);
281 	free(a->canon_enc);
282 	free(a);
283 	*pval = NULL;
284 }
285 
286 static int
287 x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
288     const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx)
289 {
290 	const unsigned char *p = *in, *q;
291 	union {
292 		STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
293 		ASN1_VALUE *a;
294 	} intname = {NULL};
295 	union {
296 		X509_NAME *x;
297 		ASN1_VALUE *a;
298 	} nm = {NULL};
299 	int i, j, ret;
300 	STACK_OF(X509_NAME_ENTRY) *entries;
301 	X509_NAME_ENTRY *entry;
302 	q = p;
303 
304 	/* Get internal representation of Name */
305 	ret = ASN1_item_ex_d2i(&intname.a, &p, len,
306 	    &X509_NAME_INTERNAL_it, tag, aclass, opt, ctx);
307 
308 	if (ret <= 0)
309 		return ret;
310 
311 	if (*val)
312 		x509_name_ex_free(val, NULL);
313 	if (!x509_name_ex_new(&nm.a, NULL))
314 		goto err;
315 	/* We've decoded it: now cache encoding */
316 	if (!BUF_MEM_grow(nm.x->bytes, p - q))
317 		goto err;
318 	memcpy(nm.x->bytes->data, q, p - q);
319 
320 	/* Convert internal representation to X509_NAME structure */
321 	for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
322 		entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i);
323 		for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
324 			entry = sk_X509_NAME_ENTRY_value(entries, j);
325 			entry->set = i;
326 			if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
327 				goto err;
328 		}
329 		sk_X509_NAME_ENTRY_free(entries);
330 	}
331 	sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
332 	ret = x509_name_canon(nm.x);
333 	if (!ret)
334 		goto err;
335 	nm.x->modified = 0;
336 	*val = nm.a;
337 	*in = p;
338 	return ret;
339 
340  err:
341 	if (nm.x != NULL)
342 		X509_NAME_free(nm.x);
343 	ASN1error(ERR_R_NESTED_ASN1_ERROR);
344 	return 0;
345 }
346 
347 static int
348 x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it,
349     int tag, int aclass)
350 {
351 	int ret;
352 	X509_NAME *a = (X509_NAME *)*val;
353 
354 	if (a->modified) {
355 		ret = x509_name_encode(a);
356 		if (ret < 0)
357 			return ret;
358 		ret = x509_name_canon(a);
359 		if (ret < 0)
360 			return ret;
361 	}
362 	ret = a->bytes->length;
363 	if (out != NULL) {
364 		memcpy(*out, a->bytes->data, ret);
365 		*out += ret;
366 	}
367 	return ret;
368 }
369 
370 static void
371 local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
372 {
373 	sk_X509_NAME_ENTRY_free(ne);
374 }
375 
376 static void
377 local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
378 {
379 	sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
380 }
381 
382 static int
383 x509_name_encode(X509_NAME *a)
384 {
385 	union {
386 		STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
387 		ASN1_VALUE *a;
388 	} intname = {NULL};
389 	int len;
390 	unsigned char *p;
391 	STACK_OF(X509_NAME_ENTRY) *entries = NULL;
392 	X509_NAME_ENTRY *entry;
393 	int i, set = -1;
394 
395 	intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null();
396 	if (!intname.s)
397 		goto memerr;
398 	for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
399 		entry = sk_X509_NAME_ENTRY_value(a->entries, i);
400 		if (entry->set != set) {
401 			entries = sk_X509_NAME_ENTRY_new_null();
402 			if (!entries)
403 				goto memerr;
404 			if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s,
405 			    entries))
406 				goto memerr;
407 			set = entry->set;
408 		}
409 		if (entries == NULL /* if entry->set is bogusly -1 */ ||
410 		    !sk_X509_NAME_ENTRY_push(entries, entry))
411 			goto memerr;
412 	}
413 	len = ASN1_item_ex_i2d(&intname.a, NULL,
414 	    &X509_NAME_INTERNAL_it, -1, -1);
415 	if (!BUF_MEM_grow(a->bytes, len))
416 		goto memerr;
417 	p = (unsigned char *)a->bytes->data;
418 	ASN1_item_ex_i2d(&intname.a, &p, &X509_NAME_INTERNAL_it,
419 	    -1, -1);
420 	sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
421 	    local_sk_X509_NAME_ENTRY_free);
422 	a->modified = 0;
423 	return len;
424 
425  memerr:
426 	sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
427 	    local_sk_X509_NAME_ENTRY_free);
428 	ASN1error(ERR_R_MALLOC_FAILURE);
429 	return -1;
430 }
431 
432 static int
433 x509_name_ex_print(BIO *out, ASN1_VALUE **pval, int indent, const char *fname,
434     const ASN1_PCTX *pctx)
435 {
436 	if (X509_NAME_print_ex(out, (X509_NAME *)*pval, indent,
437 	    pctx->nm_flags) <= 0)
438 		return 0;
439 	return 2;
440 }
441 
442 /* This function generates the canonical encoding of the Name structure.
443  * In it all strings are converted to UTF8, leading, trailing and
444  * multiple spaces collapsed, converted to lower case and the leading
445  * SEQUENCE header removed.
446  *
447  * In future we could also normalize the UTF8 too.
448  *
449  * By doing this comparison of Name structures can be rapidly
450  * performed by just using memcmp() of the canonical encoding.
451  * By omitting the leading SEQUENCE name constraints of type
452  * dirName can also be checked with a simple memcmp().
453  */
454 
455 static int
456 x509_name_canon(X509_NAME *a)
457 {
458 	unsigned char *p;
459 	STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
460 	STACK_OF(X509_NAME_ENTRY) *entries = NULL;
461 	X509_NAME_ENTRY *entry, *tmpentry = NULL;
462 	int i, len, set = -1, ret = 0;
463 
464 	if (a->canon_enc) {
465 		free(a->canon_enc);
466 		a->canon_enc = NULL;
467 	}
468 	/* Special case: empty X509_NAME => null encoding */
469 	if (sk_X509_NAME_ENTRY_num(a->entries) == 0) {
470 		a->canon_enclen = 0;
471 		return 1;
472 	}
473 	intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
474 	if (!intname)
475 		goto err;
476 	for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
477 		entry = sk_X509_NAME_ENTRY_value(a->entries, i);
478 		if (entry->set != set) {
479 			entries = sk_X509_NAME_ENTRY_new_null();
480 			if (!entries)
481 				goto err;
482 			if (sk_STACK_OF_X509_NAME_ENTRY_push(intname,
483 			    entries) == 0) {
484 				sk_X509_NAME_ENTRY_free(entries);
485 				goto err;
486 			}
487 			set = entry->set;
488 		}
489 		tmpentry = X509_NAME_ENTRY_new();
490 		if (tmpentry == NULL)
491 			goto err;
492 		tmpentry->object = OBJ_dup(entry->object);
493 		if (tmpentry->object == NULL)
494 			goto err;
495 		if (!asn1_string_canon(tmpentry->value, entry->value))
496 			goto err;
497 		if (entries == NULL /* if entry->set is bogusly -1 */ ||
498 		    !sk_X509_NAME_ENTRY_push(entries, tmpentry))
499 			goto err;
500 		tmpentry = NULL;
501 	}
502 
503 	/* Finally generate encoding */
504 	len = i2d_name_canon(intname, NULL);
505 	if (len < 0)
506 		goto err;
507 	p = malloc(len);
508 	if (p == NULL)
509 		goto err;
510 	a->canon_enc = p;
511 	a->canon_enclen = len;
512 	i2d_name_canon(intname, &p);
513 	ret = 1;
514 
515  err:
516 	if (tmpentry)
517 		X509_NAME_ENTRY_free(tmpentry);
518 	if (intname)
519 		sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
520 		    local_sk_X509_NAME_ENTRY_pop_free);
521 	return ret;
522 }
523 
524 /* Bitmap of all the types of string that will be canonicalized. */
525 
526 #define ASN1_MASK_CANON	\
527 	(B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
528 	| B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
529 	| B_ASN1_VISIBLESTRING)
530 
531 
532 static int
533 asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
534 {
535 	unsigned char *to, *from;
536 	int len, i;
537 
538 	/* If type not in bitmask just copy string across */
539 	if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) {
540 		if (!ASN1_STRING_copy(out, in))
541 			return 0;
542 		return 1;
543 	}
544 
545 	out->type = V_ASN1_UTF8STRING;
546 	out->length = ASN1_STRING_to_UTF8(&out->data, in);
547 	if (out->length == -1)
548 		return 0;
549 
550 	to = out->data;
551 	from = to;
552 
553 	len = out->length;
554 
555 	/* Convert string in place to canonical form.
556 	 * Ultimately we may need to handle a wider range of characters
557 	 * but for now ignore anything with MSB set and rely on the
558 	 * isspace() and tolower() functions.
559 	 */
560 
561 	/* Ignore leading spaces */
562 	while ((len > 0) && !(*from & 0x80) && isspace(*from)) {
563 		from++;
564 		len--;
565 	}
566 
567 	to = from + len - 1;
568 
569 	/* Ignore trailing spaces */
570 	while ((len > 0) && !(*to & 0x80) && isspace(*to)) {
571 		to--;
572 		len--;
573 	}
574 
575 	to = out->data;
576 
577 	i = 0;
578 	while (i < len) {
579 		/* If MSB set just copy across */
580 		if (*from & 0x80) {
581 			*to++ = *from++;
582 			i++;
583 		}
584 		/* Collapse multiple spaces */
585 		else if (isspace(*from)) {
586 			/* Copy one space across */
587 			*to++ = ' ';
588 			/* Ignore subsequent spaces. Note: don't need to
589 			 * check len here because we know the last
590 			 * character is a non-space so we can't overflow.
591 			 */
592 			do {
593 				from++;
594 				i++;
595 			} while (!(*from & 0x80) && isspace(*from));
596 		} else {
597 			*to++ = tolower(*from);
598 			from++;
599 			i++;
600 		}
601 	}
602 
603 	out->length = to - out->data;
604 
605 	return 1;
606 }
607 
608 static int
609 i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname, unsigned char **in)
610 {
611 	int i, len, ltmp;
612 	ASN1_VALUE *v;
613 	STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
614 
615 	len = 0;
616 	for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) {
617 		v = sk_ASN1_VALUE_value(intname, i);
618 		ltmp = ASN1_item_ex_i2d(&v, in,
619 		    &X509_NAME_ENTRIES_it, -1, -1);
620 		if (ltmp < 0)
621 			return ltmp;
622 		len += ltmp;
623 	}
624 	return len;
625 }
626 
627 int
628 X509_NAME_set(X509_NAME **xn, X509_NAME *name)
629 {
630 	if (*xn == name)
631 		return *xn != NULL;
632 	if ((name = X509_NAME_dup(name)) == NULL)
633 		return 0;
634 	X509_NAME_free(*xn);
635 	*xn = name;
636 	return 1;
637 }
638 
639 int
640 X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, size_t *pderlen)
641 {
642 	/* Make sure encoding is valid. */
643 	if (i2d_X509_NAME(nm, NULL) <= 0)
644 		return 0;
645 	if (pder != NULL)
646 		*pder = (unsigned char *)nm->bytes->data;
647 	if (pderlen != NULL)
648 		*pderlen = nm->bytes->length;
649 	return 1;
650 }
651