xref: /openbsd-src/lib/libcrypto/x509/x509_utl.c (revision 53555c846a0a6f917dbd0a191f826da995ab1c42)
1 /* $OpenBSD: x509_utl.c,v 1.25 2024/12/24 10:52:43 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 
59 #include <ctype.h>
60 #include <limits.h>
61 #include <stdio.h>
62 #include <string.h>
63 
64 #include <openssl/asn1.h>
65 #include <openssl/bn.h>
66 #include <openssl/conf.h>
67 #include <openssl/err.h>
68 #include <openssl/x509v3.h>
69 
70 #include "conf_local.h"
71 
72 #include "bytestring.h"
73 
74 /*
75  * Match reference identifiers starting with "." to any sub-domain. This
76  * flag is set implicitly when the subject reference identity is a DNS name.
77  */
78 #define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000
79 
80 static char *bn_to_string(const BIGNUM *bn);
81 static char *strip_spaces(char *name);
82 static int sk_strcmp(const char * const *a, const char * const *b);
83 static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
84     GENERAL_NAMES *gens);
85 static void str_free(OPENSSL_STRING str);
86 static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
87 
88 static int ipv4_from_asc(unsigned char *v4, const char *in);
89 static int ipv6_from_asc(unsigned char *v6, const char *in);
90 static int ipv6_cb(const char *elem, int len, void *usr);
91 static int ipv6_hex(unsigned char *out, const char *in, int inlen);
92 
93 /* Add a CONF_VALUE name-value pair to stack. */
94 int
95 X509V3_add_value(const char *name, const char *value,
96     STACK_OF(CONF_VALUE) **out_extlist)
97 {
98 	STACK_OF(CONF_VALUE) *extlist = NULL;
99 	CONF_VALUE *conf_value = NULL;
100 	int ret = 0;
101 
102 	if ((conf_value = calloc(1, sizeof(*conf_value))) == NULL) {
103 		X509V3error(ERR_R_MALLOC_FAILURE);
104 		goto err;
105 	}
106 	if (name != NULL) {
107 		if ((conf_value->name = strdup(name)) == NULL) {
108 			X509V3error(ERR_R_MALLOC_FAILURE);
109 			goto err;
110 		}
111 	}
112 	if (value != NULL) {
113 		if ((conf_value->value = strdup(value)) == NULL) {
114 			X509V3error(ERR_R_MALLOC_FAILURE);
115 			goto err;
116 		}
117 	}
118 
119 	if ((extlist = *out_extlist) == NULL)
120 		extlist = sk_CONF_VALUE_new_null();
121 	if (extlist == NULL) {
122 		X509V3error(ERR_R_MALLOC_FAILURE);
123 		goto err;
124 	}
125 
126 	if (!sk_CONF_VALUE_push(extlist, conf_value)) {
127 		X509V3error(ERR_R_MALLOC_FAILURE);
128 		goto err;
129 	}
130 	conf_value = NULL;
131 
132 	*out_extlist = extlist;
133 	extlist = NULL;
134 
135 	ret = 1;
136 
137  err:
138 	if (extlist != *out_extlist)
139 		sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free);
140 	X509V3_conf_free(conf_value);
141 
142 	return ret;
143 }
144 
145 int
146 X509V3_add_value_uchar(const char *name, const unsigned char *value,
147     STACK_OF(CONF_VALUE) **extlist)
148 {
149 	return X509V3_add_value(name, (const char *)value, extlist);
150 }
151 
152 /* Free function for STACK_OF(CONF_VALUE) */
153 
154 void
155 X509V3_conf_free(CONF_VALUE *conf)
156 {
157 	if (!conf)
158 		return;
159 	free(conf->name);
160 	free(conf->value);
161 	free(conf->section);
162 	free(conf);
163 }
164 LCRYPTO_ALIAS(X509V3_conf_free);
165 
166 int
167 X509V3_add_value_bool(const char *name, int asn1_bool,
168     STACK_OF(CONF_VALUE) **extlist)
169 {
170 	if (asn1_bool)
171 		return X509V3_add_value(name, "TRUE", extlist);
172 	return X509V3_add_value(name, "FALSE", extlist);
173 }
174 
175 static char *
176 bn_to_string(const BIGNUM *bn)
177 {
178 	const char *sign = "";
179 	char *bnstr, *hex;
180 	char *ret = NULL;
181 
182 	/* Only display small numbers in decimal, as conversion is quadratic. */
183 	if (BN_num_bits(bn) < 128)
184 		return BN_bn2dec(bn);
185 
186 	if ((hex = bnstr = BN_bn2hex(bn)) == NULL)
187 		goto err;
188 
189 	if (BN_is_negative(bn)) {
190 		sign = "-";
191 		hex++;
192 	}
193 
194 	if (asprintf(&ret, "%s0x%s", sign, hex) == -1)
195 		ret = NULL;
196 
197  err:
198 	free(bnstr);
199 	return ret;
200 }
201 
202 char *
203 i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a)
204 {
205 	BIGNUM *bntmp;
206 	char *strtmp = NULL;
207 
208 	if (a == NULL)
209 		return NULL;
210 	if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL ||
211 	    (strtmp = bn_to_string(bntmp)) == NULL)
212 		X509V3error(ERR_R_MALLOC_FAILURE);
213 	BN_free(bntmp);
214 	return strtmp;
215 }
216 LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED);
217 
218 char *
219 i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *e)
220 {
221 	const BIT_STRING_BITNAME *enam;
222 	long strval;
223 
224 	strval = ASN1_ENUMERATED_get(e);
225 	for (enam = method->usr_data; enam->lname; enam++) {
226 		if (strval == enam->bitnum)
227 			return strdup(enam->lname);
228 	}
229 	return i2s_ASN1_ENUMERATED(method, e);
230 }
231 LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED_TABLE);
232 
233 char *
234 i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a)
235 {
236 	BIGNUM *bntmp;
237 	char *strtmp = NULL;
238 
239 	if (a == NULL)
240 		return NULL;
241 	if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL ||
242 	    (strtmp = bn_to_string(bntmp)) == NULL)
243 		X509V3error(ERR_R_MALLOC_FAILURE);
244 	BN_free(bntmp);
245 	return strtmp;
246 }
247 LCRYPTO_ALIAS(i2s_ASN1_INTEGER);
248 
249 ASN1_INTEGER *
250 s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
251 {
252 	BIGNUM *bn = NULL;
253 	ASN1_INTEGER *aint;
254 	int isneg = 0, ishex = 0;
255 	int ret;
256 
257 	if (!value) {
258 		X509V3error(X509V3_R_INVALID_NULL_VALUE);
259 		return NULL;
260 	}
261 	if ((bn = BN_new()) == NULL) {
262 		X509V3error(ERR_R_MALLOC_FAILURE);
263 		return NULL;
264 	}
265 	if (value[0] == '-') {
266 		value++;
267 		isneg = 1;
268 	}
269 
270 	if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
271 		value += 2;
272 		ishex = 1;
273 	}
274 
275 	if (ishex)
276 		ret = BN_hex2bn(&bn, value);
277 	else
278 		ret = BN_dec2bn(&bn, value);
279 
280 	if (!ret || value[ret]) {
281 		BN_free(bn);
282 		X509V3error(X509V3_R_BN_DEC2BN_ERROR);
283 		return NULL;
284 	}
285 
286 	if (BN_is_zero(bn))
287 		isneg = 0;
288 
289 	aint = BN_to_ASN1_INTEGER(bn, NULL);
290 	BN_free(bn);
291 	if (!aint) {
292 		X509V3error(X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
293 		return NULL;
294 	}
295 	if (isneg)
296 		aint->type |= V_ASN1_NEG;
297 	return aint;
298 }
299 LCRYPTO_ALIAS(s2i_ASN1_INTEGER);
300 
301 int
302 X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint,
303     STACK_OF(CONF_VALUE) **extlist)
304 {
305 	char *strtmp;
306 	int ret;
307 
308 	if (!aint)
309 		return 1;
310 	if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
311 		return 0;
312 	ret = X509V3_add_value(name, strtmp, extlist);
313 	free(strtmp);
314 	return ret;
315 }
316 
317 int
318 X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool)
319 {
320 	char *btmp;
321 
322 	if (!(btmp = value->value))
323 		goto err;
324 	if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") ||
325 	    !strcmp(btmp, "Y") || !strcmp(btmp, "y") ||
326 	    !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
327 		*asn1_bool = 0xff;
328 		return 1;
329 	} else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") ||
330 	    !strcmp(btmp, "N") || !strcmp(btmp, "n") ||
331 	    !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
332 		*asn1_bool = 0;
333 		return 1;
334 	}
335 
336  err:
337 	X509V3error(X509V3_R_INVALID_BOOLEAN_STRING);
338 	X509V3_conf_err(value);
339 	return 0;
340 }
341 
342 int
343 X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint)
344 {
345 	ASN1_INTEGER *itmp;
346 
347 	if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
348 		X509V3_conf_err(value);
349 		return 0;
350 	}
351 	*aint = itmp;
352 	return 1;
353 }
354 
355 #define HDR_NAME	1
356 #define HDR_VALUE	2
357 
358 /*#define DEBUG*/
359 
360 STACK_OF(CONF_VALUE) *
361 X509V3_parse_list(const char *line)
362 {
363 	char *p, *q, c;
364 	char *ntmp, *vtmp;
365 	STACK_OF(CONF_VALUE) *values = NULL;
366 	char *linebuf;
367 	int state;
368 
369 	/* We are going to modify the line so copy it first */
370 	if ((linebuf = strdup(line)) == NULL) {
371 		X509V3error(ERR_R_MALLOC_FAILURE);
372 		goto err;
373 	}
374 	state = HDR_NAME;
375 	ntmp = NULL;
376 
377 	/* Go through all characters */
378 	for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') &&
379 	    (c != '\n'); p++) {
380 
381 		switch (state) {
382 		case HDR_NAME:
383 			if (c == ':') {
384 				state = HDR_VALUE;
385 				*p = 0;
386 				ntmp = strip_spaces(q);
387 				if (!ntmp) {
388 					X509V3error(X509V3_R_INVALID_NULL_NAME);
389 					goto err;
390 				}
391 				q = p + 1;
392 			} else if (c == ',') {
393 				*p = 0;
394 				ntmp = strip_spaces(q);
395 				q = p + 1;
396 				if (!ntmp) {
397 					X509V3error(X509V3_R_INVALID_NULL_NAME);
398 					goto err;
399 				}
400 				if (!X509V3_add_value(ntmp, NULL, &values))
401 					goto err;
402 			}
403 			break;
404 
405 		case HDR_VALUE:
406 			if (c == ',') {
407 				state = HDR_NAME;
408 				*p = 0;
409 				vtmp = strip_spaces(q);
410 				if (!vtmp) {
411 					X509V3error(X509V3_R_INVALID_NULL_VALUE);
412 					goto err;
413 				}
414 				if (!X509V3_add_value(ntmp, vtmp, &values))
415 					goto err;
416 				ntmp = NULL;
417 				q = p + 1;
418 			}
419 
420 		}
421 	}
422 
423 	if (state == HDR_VALUE) {
424 		vtmp = strip_spaces(q);
425 		if (!vtmp) {
426 			X509V3error(X509V3_R_INVALID_NULL_VALUE);
427 			goto err;
428 		}
429 		if (!X509V3_add_value(ntmp, vtmp, &values))
430 			goto err;
431 	} else {
432 		ntmp = strip_spaces(q);
433 		if (!ntmp) {
434 			X509V3error(X509V3_R_INVALID_NULL_NAME);
435 			goto err;
436 		}
437 		if (!X509V3_add_value(ntmp, NULL, &values))
438 			goto err;
439 	}
440 	free(linebuf);
441 	return values;
442 
443  err:
444 	free(linebuf);
445 	sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
446 	return NULL;
447 }
448 LCRYPTO_ALIAS(X509V3_parse_list);
449 
450 /* Delete leading and trailing spaces from a string */
451 static char *
452 strip_spaces(char *name)
453 {
454 	char *p, *q;
455 
456 	/* Skip over leading spaces */
457 	p = name;
458 	while (*p && isspace((unsigned char)*p))
459 		p++;
460 	if (!*p)
461 		return NULL;
462 	q = p + strlen(p) - 1;
463 	while ((q != p) && isspace((unsigned char)*q))
464 		q--;
465 	if (p != q)
466 		q[1] = 0;
467 	if (!*p)
468 		return NULL;
469 	return p;
470 }
471 
472 static const char hex_digits[] = "0123456789ABCDEF";
473 
474 char *
475 hex_to_string(const unsigned char *buffer, long len)
476 {
477 	CBB cbb;
478 	CBS cbs;
479 	uint8_t *out = NULL;
480 	uint8_t c;
481 	size_t out_len;
482 
483 	if (!CBB_init(&cbb, 0))
484 		goto err;
485 
486 	if (len < 0)
487 		goto err;
488 
489 	CBS_init(&cbs, buffer, len);
490 	while (CBS_len(&cbs) > 0) {
491 		if (!CBS_get_u8(&cbs, &c))
492 			goto err;
493 		if (!CBB_add_u8(&cbb, hex_digits[c >> 4]))
494 			goto err;
495 		if (!CBB_add_u8(&cbb, hex_digits[c & 0xf]))
496 			goto err;
497 		if (CBS_len(&cbs) > 0) {
498 			if (!CBB_add_u8(&cbb, ':'))
499 				goto err;
500 		}
501 	}
502 
503 	if (!CBB_add_u8(&cbb, '\0'))
504 		goto err;
505 
506 	if (!CBB_finish(&cbb, &out, &out_len))
507 		goto err;
508 
509  err:
510 	CBB_cleanup(&cbb);
511 
512 	return out;
513 }
514 LCRYPTO_ALIAS(hex_to_string);
515 
516 static int
517 x509_skip_colons_cbs(CBS *cbs)
518 {
519 	uint8_t c;
520 
521 	while (CBS_len(cbs) > 0) {
522 		if (!CBS_peek_u8(cbs, &c))
523 			return 0;
524 		if (c != ':')
525 			return 1;
526 		if (!CBS_get_u8(cbs, &c))
527 			return 0;
528 	}
529 
530 	return 1;
531 }
532 
533 static int
534 x509_get_xdigit_nibble_cbs(CBS *cbs, uint8_t *out_nibble)
535 {
536 	uint8_t c;
537 
538 	if (!CBS_get_u8(cbs, &c))
539 		return 0;
540 
541 	if (c >= '0' && c <= '9') {
542 		*out_nibble = c - '0';
543 		return 1;
544 	}
545 	if (c >= 'a' && c <= 'f') {
546 		*out_nibble = c - 'a' + 10;
547 		return 1;
548 	}
549 	if (c >= 'A' && c <= 'F') {
550 		*out_nibble = c - 'A' + 10;
551 		return 1;
552 	}
553 
554 	X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT);
555 	return 0;
556 }
557 
558 unsigned char *
559 string_to_hex(const char *str, long *len)
560 {
561 	CBB cbb;
562 	CBS cbs;
563 	uint8_t *out = NULL;
564 	size_t out_len;
565 	uint8_t hi, lo;
566 
567 	*len = 0;
568 
569 	if (!CBB_init(&cbb, 0))
570 		goto err;
571 
572 	if (str == NULL) {
573 		X509V3error(X509V3_R_INVALID_NULL_ARGUMENT);
574 		goto err;
575 	}
576 
577 	CBS_init(&cbs, str, strlen(str));
578 	while (CBS_len(&cbs) > 0) {
579 		/*
580 		 * Skipping only a single colon between two pairs of digits
581 		 * would make more sense - history...
582 		 */
583 		if (!x509_skip_colons_cbs(&cbs))
584 			goto err;
585 		/* Another historic idiocy. */
586 		if (CBS_len(&cbs) == 0)
587 			break;
588 		if (!x509_get_xdigit_nibble_cbs(&cbs, &hi))
589 			goto err;
590 		if (CBS_len(&cbs) == 0) {
591 			X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS);
592 			goto err;
593 		}
594 		if (!x509_get_xdigit_nibble_cbs(&cbs, &lo))
595 			goto err;
596 		if (!CBB_add_u8(&cbb, hi << 4 | lo))
597 			goto err;
598 	}
599 
600 	if (!CBB_finish(&cbb, &out, &out_len))
601 		goto err;
602 	if (out_len > LONG_MAX) {
603 		freezero(out, out_len);
604 		out = NULL;
605 		goto err;
606 	}
607 
608 	*len = out_len;
609 
610  err:
611 	CBB_cleanup(&cbb);
612 
613 	return out;
614 }
615 LCRYPTO_ALIAS(string_to_hex);
616 
617 /* V2I name comparison function: returns zero if 'name' matches
618  * cmp or cmp.*
619  */
620 
621 int
622 name_cmp(const char *name, const char *cmp)
623 {
624 	int len, ret;
625 	char c;
626 
627 	len = strlen(cmp);
628 	if ((ret = strncmp(name, cmp, len)))
629 		return ret;
630 	c = name[len];
631 	if (!c || (c=='.'))
632 		return 0;
633 	return 1;
634 }
635 
636 static int
637 sk_strcmp(const char * const *a, const char * const *b)
638 {
639 	return strcmp(*a, *b);
640 }
641 
642 STACK_OF(OPENSSL_STRING) *
643 X509_get1_email(X509 *x)
644 {
645 	GENERAL_NAMES *gens;
646 	STACK_OF(OPENSSL_STRING) *ret;
647 
648 	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
649 	ret = get_email(X509_get_subject_name(x), gens);
650 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
651 	return ret;
652 }
653 LCRYPTO_ALIAS(X509_get1_email);
654 
655 STACK_OF(OPENSSL_STRING) *
656 X509_get1_ocsp(X509 *x)
657 {
658 	AUTHORITY_INFO_ACCESS *info;
659 	STACK_OF(OPENSSL_STRING) *ret = NULL;
660 	int i;
661 
662 	info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
663 	if (!info)
664 		return NULL;
665 	for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
666 		ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
667 		if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
668 			if (ad->location->type == GEN_URI) {
669 				if (!append_ia5(&ret,
670 				    ad->location->d.uniformResourceIdentifier))
671 					break;
672 			}
673 		}
674 	}
675 	AUTHORITY_INFO_ACCESS_free(info);
676 	return ret;
677 }
678 LCRYPTO_ALIAS(X509_get1_ocsp);
679 
680 STACK_OF(OPENSSL_STRING) *
681 X509_REQ_get1_email(X509_REQ *x)
682 {
683 	GENERAL_NAMES *gens;
684 	STACK_OF(X509_EXTENSION) *exts;
685 	STACK_OF(OPENSSL_STRING) *ret;
686 
687 	exts = X509_REQ_get_extensions(x);
688 	gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
689 	ret = get_email(X509_REQ_get_subject_name(x), gens);
690 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
691 	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
692 	return ret;
693 }
694 LCRYPTO_ALIAS(X509_REQ_get1_email);
695 
696 
697 static STACK_OF(OPENSSL_STRING) *
698 get_email(X509_NAME *name, GENERAL_NAMES *gens)
699 {
700 	STACK_OF(OPENSSL_STRING) *ret = NULL;
701 	X509_NAME_ENTRY *ne;
702 	ASN1_IA5STRING *email;
703 	GENERAL_NAME *gen;
704 	int i;
705 
706 	/* Now add any email address(es) to STACK */
707 	i = -1;
708 
709 	/* First supplied X509_NAME */
710 	while ((i = X509_NAME_get_index_by_NID(name,
711 	    NID_pkcs9_emailAddress, i)) >= 0) {
712 		ne = X509_NAME_get_entry(name, i);
713 		email = X509_NAME_ENTRY_get_data(ne);
714 		if (!append_ia5(&ret, email))
715 			return NULL;
716 	}
717 	for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
718 		gen = sk_GENERAL_NAME_value(gens, i);
719 		if (gen->type != GEN_EMAIL)
720 			continue;
721 		if (!append_ia5(&ret, gen->d.ia5))
722 			return NULL;
723 	}
724 	return ret;
725 }
726 
727 static void
728 str_free(OPENSSL_STRING str)
729 {
730 	free(str);
731 }
732 
733 static int
734 append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
735 {
736 	char *emtmp;
737 
738 	/* First some sanity checks */
739 	if (email->type != V_ASN1_IA5STRING)
740 		return 1;
741 	if (!email->data || !email->length)
742 		return 1;
743 	if (!*sk)
744 		*sk = sk_OPENSSL_STRING_new(sk_strcmp);
745 	if (!*sk)
746 		return 0;
747 	/* Don't add duplicates */
748 	if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
749 		return 1;
750 	emtmp = strdup((char *)email->data);
751 	if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
752 		X509_email_free(*sk);
753 		*sk = NULL;
754 		return 0;
755 	}
756 	return 1;
757 }
758 
759 void
760 X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
761 {
762 	sk_OPENSSL_STRING_pop_free(sk, str_free);
763 }
764 LCRYPTO_ALIAS(X509_email_free);
765 
766 typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len,
767     const unsigned char *subject, size_t subject_len, unsigned int flags);
768 
769 /* Skip pattern prefix to match "wildcard" subject */
770 static void
771 skip_prefix(const unsigned char **p, size_t *plen, const unsigned char *subject,
772     size_t subject_len, unsigned int flags)
773 {
774 	const unsigned char *pattern = *p;
775 	size_t pattern_len = *plen;
776 
777 	/*
778 	 * If subject starts with a leading '.' followed by more octets, and
779 	 * pattern is longer, compare just an equal-length suffix with the
780 	 * full subject (starting at the '.'), provided the prefix contains
781 	 * no NULs.
782 	 */
783 	if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
784 		return;
785 
786 	while (pattern_len > subject_len && *pattern) {
787 		if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
788 		    *pattern == '.')
789 			break;
790 		++pattern;
791 		--pattern_len;
792 	}
793 
794 	/* Skip if entire prefix acceptable */
795 	if (pattern_len == subject_len) {
796 		*p = pattern;
797 		*plen = pattern_len;
798 	}
799 }
800 
801 /*
802  * Open/BoringSSL uses memcmp for "equal_case" while their
803  * "equal_nocase" function is a hand-rolled strncasecmp that does not
804  * allow \0 in the pattern. Since an embedded \0 is likely a sign of
805  * problems, we simply don't allow it in either case, and then we use
806  * standard libc functions.
807  */
808 
809 /* Compare using strncasecmp */
810 static int
811 equal_nocase(const unsigned char *pattern, size_t pattern_len,
812     const unsigned char *subject, size_t subject_len, unsigned int flags)
813 {
814 	if (memchr(pattern, '\0', pattern_len) != NULL)
815 		return 0;
816 	if (memchr(subject, '\0', subject_len) != NULL)
817 		return 0;
818 	skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
819 	if (pattern_len != subject_len)
820 		return 0;
821 	return (strncasecmp(pattern, subject, pattern_len) == 0);
822 }
823 
824 /* Compare using strncmp. */
825 static int
826 equal_case(const unsigned char *pattern, size_t pattern_len,
827     const unsigned char *subject, size_t subject_len, unsigned int flags)
828 {
829 	if (memchr(pattern, 0, pattern_len) != NULL)
830 		return 0;
831 	if (memchr(subject, 0, subject_len) != NULL)
832 		return 0;
833 	skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
834 	if (pattern_len != subject_len)
835 		return 0;
836 	return (strncmp(pattern, subject, pattern_len) == 0);
837 }
838 
839 /*
840  * RFC 5280, section 7.5, requires that only the domain is compared in a
841  * case-insensitive manner.
842  */
843 static int
844 equal_email(const unsigned char *a, size_t a_len, const unsigned char *b,
845     size_t b_len, unsigned int unused_flags)
846 {
847 	size_t pos = a_len;
848 	if (a_len != b_len)
849 		return 0;
850 	/*
851 	 * We search backwards for the '@' character, so that we do not have to
852 	 * deal with quoted local-parts.  The domain part is compared in a
853 	 * case-insensitive manner.
854 	 */
855 	while (pos > 0) {
856 		pos--;
857 		if (a[pos] == '@' || b[pos] == '@') {
858 			if (!equal_nocase(a + pos, a_len - pos, b + pos,
859 			    a_len - pos, 0))
860 				return 0;
861 			break;
862 		}
863 	}
864 	if (pos == 0)
865 		pos = a_len;
866 	return equal_case(a, pos, b, pos, 0);
867 }
868 
869 /*
870  * Compare the prefix and suffix with the subject, and check that the
871  * characters in-between are valid.
872  */
873 static int
874 wildcard_match(const unsigned char *prefix, size_t prefix_len,
875     const unsigned char *suffix, size_t suffix_len,
876     const unsigned char *subject, size_t subject_len, unsigned int flags)
877 {
878 	const unsigned char *wildcard_start;
879 	const unsigned char *wildcard_end;
880 	const unsigned char *p;
881 	int allow_multi = 0;
882 	int allow_idna = 0;
883 
884 	if (subject_len < prefix_len + suffix_len)
885 		return 0;
886 	if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
887 		return 0;
888 	wildcard_start = subject + prefix_len;
889 	wildcard_end = subject + (subject_len - suffix_len);
890 	if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
891 		return 0;
892 	/*
893 	 * If the wildcard makes up the entire first label, it must match at
894 	 * least one character.
895 	 */
896 	if (prefix_len == 0 && *suffix == '.') {
897 		if (wildcard_start == wildcard_end)
898 			return 0;
899 		allow_idna = 1;
900 		if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
901 			allow_multi = 1;
902 	}
903 	/* IDNA labels cannot match partial wildcards */
904 	if (!allow_idna &&
905 	    subject_len >= 4
906 	    && strncasecmp((char *)subject, "xn--", 4) == 0)
907 		return 0;
908 	/* The wildcard may match a literal '*' */
909 	if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
910 		return 1;
911 	/*
912 	 * Check that the part matched by the wildcard contains only
913 	 * permitted characters and only matches a single label unless
914 	 * allow_multi is set.
915 	 */
916 	for (p = wildcard_start; p != wildcard_end; ++p)
917 		if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') ||
918 		    ('a' <= *p && *p <= 'z') || *p == '-' ||
919 		    (allow_multi && *p == '.')))
920 			return 0;
921 	return 1;
922 }
923 
924 #define LABEL_START     (1 << 0)
925 #define LABEL_END       (1 << 1)
926 #define LABEL_HYPHEN    (1 << 2)
927 #define LABEL_IDNA      (1 << 3)
928 
929 static const unsigned char *
930 valid_star(const unsigned char *p, size_t len, unsigned int flags)
931 {
932 	const unsigned char *star = 0;
933 	size_t i;
934 	int state = LABEL_START;
935 	int dots = 0;
936 	for (i = 0; i < len; ++i) {
937 		/*
938 		 * Locate first and only legal wildcard, either at the start
939 		 * or end of a non-IDNA first and not final label.
940 		 */
941 		if (p[i] == '*') {
942 			int atstart = (state & LABEL_START);
943 			int atend = (i == len - 1 || p[i + 1] == '.');
944 			/*
945 			 * At most one wildcard per pattern.
946 			 * No wildcards in IDNA labels.
947 			 * No wildcards after the first label.
948 			 */
949 			if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
950 				return NULL;
951 			/* Only full-label '*.example.com' wildcards? */
952 			if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
953 			    && (!atstart || !atend))
954 				return NULL;
955 			/* No 'foo*bar' wildcards */
956 			if (!atstart && !atend)
957 				return NULL;
958 			star = &p[i];
959 			state &= ~LABEL_START;
960 		} else if ((state & LABEL_START) != 0) {
961 			/*
962 			 * At the start of a label, skip any "xn--" and
963 			 * remain in the LABEL_START state, but set the
964 			 * IDNA label state
965 			 */
966 			if ((state & LABEL_IDNA) == 0 && len - i >= 4
967 			    && strncasecmp((char *)&p[i], "xn--", 4) == 0) {
968 				i += 3;
969 				state |= LABEL_IDNA;
970 				continue;
971 			}
972 			/* Labels must start with a letter or digit */
973 			state &= ~LABEL_START;
974 			if (('a' <= p[i] && p[i] <= 'z')
975 			    || ('A' <= p[i] && p[i] <= 'Z')
976 			    || ('0' <= p[i] && p[i] <= '9'))
977 				continue;
978 			return NULL;
979 		} else if (('a' <= p[i] && p[i] <= 'z')
980 		    || ('A' <= p[i] && p[i] <= 'Z')
981 		    || ('0' <= p[i] && p[i] <= '9')) {
982 			state &= LABEL_IDNA;
983 			continue;
984 		} else if (p[i] == '.') {
985 			if (state & (LABEL_HYPHEN | LABEL_START))
986 				return NULL;
987 			state = LABEL_START;
988 			++dots;
989 		} else if (p[i] == '-') {
990 			/* no domain/subdomain starts with '-' */
991 			if ((state & LABEL_START) != 0)
992 				return NULL;
993 			state |= LABEL_HYPHEN;
994 		} else
995 			return NULL;
996 	}
997 
998 	/*
999 	 * The final label must not end in a hyphen or ".", and
1000 	 * there must be at least two dots after the star.
1001 	 */
1002 	if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
1003 		return NULL;
1004 	return star;
1005 }
1006 
1007 /* Compare using wildcards. */
1008 static int
1009 equal_wildcard(const unsigned char *pattern, size_t pattern_len,
1010     const unsigned char *subject, size_t subject_len, unsigned int flags)
1011 {
1012 	const unsigned char *star = NULL;
1013 
1014 	/*
1015 	 * Subject names starting with '.' can only match a wildcard pattern
1016 	 * via a subject sub-domain pattern suffix match.
1017 	 */
1018 	if (!(subject_len > 1 && subject[0] == '.'))
1019 		star = valid_star(pattern, pattern_len, flags);
1020 	if (star == NULL)
1021 		return equal_nocase(pattern, pattern_len,
1022 		    subject, subject_len, flags);
1023 	return wildcard_match(pattern, star - pattern,
1024 	    star + 1, (pattern + pattern_len) - star - 1,
1025 	    subject, subject_len, flags);
1026 }
1027 
1028 /*
1029  * Compare an ASN1_STRING to a supplied string. If they match return 1. If
1030  * cmp_type > 0 only compare if string matches the type, otherwise convert it
1031  * to UTF8.
1032  */
1033 
1034 static int
1035 do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
1036     unsigned int flags, const char *b, size_t blen, char **peername)
1037 {
1038 	int rv = 0;
1039 
1040 	if (!a->data || !a->length)
1041 		return 0;
1042 	if (cmp_type > 0) {
1043 		if (cmp_type != a->type)
1044 			return 0;
1045 		if (cmp_type == V_ASN1_IA5STRING)
1046 			rv = equal(a->data, a->length, (unsigned char *)b,
1047 			    blen, flags);
1048 		else if (a->length == (int)blen && !memcmp(a->data, b, blen))
1049 			rv = 1;
1050 		if (rv > 0 && peername &&
1051 		    (*peername = strndup((char *)a->data, a->length)) == NULL)
1052 			rv = -1;
1053 	} else {
1054 		int astrlen;
1055 		unsigned char *astr = NULL;
1056 		astrlen = ASN1_STRING_to_UTF8(&astr, a);
1057 		if (astrlen < 0)
1058 			return -1;
1059 		rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
1060 		if (rv > 0 && peername &&
1061 		    (*peername = strndup((char *)astr, astrlen)) == NULL)
1062 			rv = -1;
1063 		free(astr);
1064 	}
1065 	return rv;
1066 }
1067 
1068 static int
1069 do_x509_check(X509 *x, const char *chk, size_t chklen, unsigned int flags,
1070     int check_type, char **peername)
1071 {
1072 	GENERAL_NAMES *gens = NULL;
1073 	X509_NAME *name = NULL;
1074 	size_t i;
1075 	int j;
1076 	int cnid = NID_undef;
1077 	int alt_type;
1078 	int san_present = 0;
1079 	int rv = 0;
1080 	equal_fn equal;
1081 
1082 	/* See below, this flag is internal-only */
1083 	flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
1084 	if (check_type == GEN_EMAIL) {
1085 		cnid = NID_pkcs9_emailAddress;
1086 		alt_type = V_ASN1_IA5STRING;
1087 		equal = equal_email;
1088 	} else if (check_type == GEN_DNS) {
1089 		if (!(flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT))
1090 			cnid = NID_commonName;
1091 		/* Implicit client-side DNS sub-domain pattern */
1092 		if (chklen > 1 && chk[0] == '.')
1093 			flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
1094 		alt_type = V_ASN1_IA5STRING;
1095 		if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
1096 			equal = equal_nocase;
1097 		else
1098 			equal = equal_wildcard;
1099 	} else {
1100 		alt_type = V_ASN1_OCTET_STRING;
1101 		equal = equal_case;
1102 	}
1103 
1104 	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
1105 	if (gens != NULL) {
1106 		for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
1107 			GENERAL_NAME *gen;
1108 			ASN1_STRING *cstr;
1109 			gen = sk_GENERAL_NAME_value(gens, i);
1110 			if (gen->type != check_type)
1111 				continue;
1112 			san_present = 1;
1113 			if (check_type == GEN_EMAIL)
1114 				cstr = gen->d.rfc822Name;
1115 			else if (check_type == GEN_DNS)
1116 				cstr = gen->d.dNSName;
1117 			else
1118 				cstr = gen->d.iPAddress;
1119 			/* Positive on success, negative on error! */
1120 			if ((rv = do_check_string(cstr, alt_type, equal, flags,
1121 			    chk, chklen, peername)) != 0)
1122 				break;
1123 		}
1124 		GENERAL_NAMES_free(gens);
1125 		if (rv != 0)
1126 			return rv;
1127 		if (cnid == NID_undef ||
1128 		    (san_present &&
1129 		    !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
1130 			return 0;
1131 	}
1132 
1133 	/* We're done if CN-ID is not pertinent */
1134 	if (cnid == NID_undef)
1135 		return 0;
1136 
1137 	j = -1;
1138 	name = X509_get_subject_name(x);
1139 	while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) {
1140 		X509_NAME_ENTRY *ne;
1141 		ASN1_STRING *str;
1142 		if ((ne = X509_NAME_get_entry(name, j)) == NULL)
1143 			return -1;
1144 		if ((str = X509_NAME_ENTRY_get_data(ne)) == NULL)
1145 			return -1;
1146 		/* Positive on success, negative on error! */
1147 		if ((rv = do_check_string(str, -1, equal, flags,
1148 			 chk, chklen, peername)) != 0)
1149 			return rv;
1150 	}
1151 	return 0;
1152 }
1153 
1154 int
1155 X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags,
1156     char **peername)
1157 {
1158 	if (chk == NULL)
1159 		return -2;
1160 	if (chklen == 0)
1161 		chklen = strlen(chk);
1162 	else if (memchr(chk, '\0', chklen))
1163 		return -2;
1164 	return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
1165 }
1166 LCRYPTO_ALIAS(X509_check_host);
1167 
1168 int
1169 X509_check_email(X509 *x, const char *chk, size_t chklen, unsigned int flags)
1170 {
1171 	if (chk == NULL)
1172 		return -2;
1173 	if (chklen == 0)
1174 		chklen = strlen(chk);
1175 	else if (memchr(chk, '\0', chklen))
1176 		return -2;
1177 	return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
1178 }
1179 LCRYPTO_ALIAS(X509_check_email);
1180 
1181 int
1182 X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
1183     unsigned int flags)
1184 {
1185 	if (chk == NULL)
1186 		return -2;
1187 	return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
1188 }
1189 LCRYPTO_ALIAS(X509_check_ip);
1190 
1191 int
1192 X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
1193 {
1194 	unsigned char ipout[16];
1195 	size_t iplen;
1196 
1197 	if (ipasc == NULL)
1198 		return -2;
1199 	iplen = (size_t)a2i_ipadd(ipout, ipasc);
1200 	if (iplen == 0)
1201 		return -2;
1202 	return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
1203 }
1204 LCRYPTO_ALIAS(X509_check_ip_asc);
1205 
1206 /* Convert IP addresses both IPv4 and IPv6 into an
1207  * OCTET STRING compatible with RFC3280.
1208  */
1209 
1210 ASN1_OCTET_STRING *
1211 a2i_IPADDRESS(const char *ipasc)
1212 {
1213 	unsigned char ipout[16];
1214 	ASN1_OCTET_STRING *ret;
1215 	int iplen;
1216 
1217 	/* If string contains a ':' assume IPv6 */
1218 
1219 	iplen = a2i_ipadd(ipout, ipasc);
1220 
1221 	if (!iplen)
1222 		return NULL;
1223 
1224 	ret = ASN1_OCTET_STRING_new();
1225 	if (!ret)
1226 		return NULL;
1227 	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
1228 		ASN1_OCTET_STRING_free(ret);
1229 		return NULL;
1230 	}
1231 	return ret;
1232 }
1233 LCRYPTO_ALIAS(a2i_IPADDRESS);
1234 
1235 ASN1_OCTET_STRING *
1236 a2i_IPADDRESS_NC(const char *ipasc)
1237 {
1238 	ASN1_OCTET_STRING *ret = NULL;
1239 	unsigned char ipout[32];
1240 	char *iptmp = NULL, *p;
1241 	int iplen1, iplen2;
1242 
1243 	p = strchr(ipasc, '/');
1244 	if (!p)
1245 		return NULL;
1246 	iptmp = strdup(ipasc);
1247 	if (!iptmp)
1248 		return NULL;
1249 	p = iptmp + (p - ipasc);
1250 	*p++ = 0;
1251 
1252 	iplen1 = a2i_ipadd(ipout, iptmp);
1253 
1254 	if (!iplen1)
1255 		goto err;
1256 
1257 	iplen2 = a2i_ipadd(ipout + iplen1, p);
1258 
1259 	free(iptmp);
1260 	iptmp = NULL;
1261 
1262 	if (!iplen2 || (iplen1 != iplen2))
1263 		goto err;
1264 
1265 	ret = ASN1_OCTET_STRING_new();
1266 	if (!ret)
1267 		goto err;
1268 	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
1269 		goto err;
1270 
1271 	return ret;
1272 
1273  err:
1274 	free(iptmp);
1275 	if (ret)
1276 		ASN1_OCTET_STRING_free(ret);
1277 	return NULL;
1278 }
1279 LCRYPTO_ALIAS(a2i_IPADDRESS_NC);
1280 
1281 
1282 int
1283 a2i_ipadd(unsigned char *ipout, const char *ipasc)
1284 {
1285 	/* If string contains a ':' assume IPv6 */
1286 
1287 	if (strchr(ipasc, ':')) {
1288 		if (!ipv6_from_asc(ipout, ipasc))
1289 			return 0;
1290 		return 16;
1291 	} else {
1292 		if (!ipv4_from_asc(ipout, ipasc))
1293 			return 0;
1294 		return 4;
1295 	}
1296 }
1297 LCRYPTO_ALIAS(a2i_ipadd);
1298 
1299 static int
1300 ipv4_from_asc(unsigned char *v4, const char *in)
1301 {
1302 	int a0, a1, a2, a3;
1303 	if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
1304 		return 0;
1305 	if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) ||
1306 	    (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
1307 		return 0;
1308 	v4[0] = a0;
1309 	v4[1] = a1;
1310 	v4[2] = a2;
1311 	v4[3] = a3;
1312 	return 1;
1313 }
1314 
1315 typedef struct {
1316 	/* Temporary store for IPV6 output */
1317 	unsigned char tmp[16];
1318 	/* Total number of bytes in tmp */
1319 	int total;
1320 	/* The position of a zero (corresponding to '::') */
1321 	int zero_pos;
1322 	/* Number of zeroes */
1323 	int zero_cnt;
1324 } IPV6_STAT;
1325 
1326 
1327 static int
1328 ipv6_from_asc(unsigned char *v6, const char *in)
1329 {
1330 	IPV6_STAT v6stat;
1331 
1332 	v6stat.total = 0;
1333 	v6stat.zero_pos = -1;
1334 	v6stat.zero_cnt = 0;
1335 
1336 	/*
1337 	 * Treat the IPv6 representation as a list of values separated by ':'.
1338 	 * The presence of a '::' will parse as one (e.g., "2001:db8::1"),
1339 	 * two (e.g., "2001:db8::") or three (e.g., "::") zero length elements.
1340 	 */
1341 	if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
1342 		return 0;
1343 
1344 	/* Now for some sanity checks */
1345 
1346 	if (v6stat.zero_pos == -1) {
1347 		/* If no '::' must have exactly 16 bytes */
1348 		if (v6stat.total != 16)
1349 			return 0;
1350 	} else {
1351 		/* If '::' must have less than 16 bytes */
1352 		if (v6stat.total == 16)
1353 			return 0;
1354 		/* More than three zeroes is an error */
1355 		if (v6stat.zero_cnt > 3)
1356 			return 0;
1357 		/* Can only have three zeroes if nothing else present */
1358 		else if (v6stat.zero_cnt == 3) {
1359 			if (v6stat.total > 0)
1360 				return 0;
1361 		}
1362 		/* Can only have two zeroes if at start or end */
1363 		else if (v6stat.zero_cnt == 2) {
1364 			if ((v6stat.zero_pos != 0) &&
1365 			    (v6stat.zero_pos != v6stat.total))
1366 				return 0;
1367 		} else
1368 			/* Can only have one zero if *not* start or end */
1369 		{
1370 			if ((v6stat.zero_pos == 0) ||
1371 			    (v6stat.zero_pos == v6stat.total))
1372 				return 0;
1373 		}
1374 	}
1375 
1376 	/* Format result */
1377 
1378 	if (v6stat.zero_pos >= 0) {
1379 		/* Copy initial part */
1380 		memcpy(v6, v6stat.tmp, v6stat.zero_pos);
1381 		/* Zero middle */
1382 		memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
1383 		/* Copy final part */
1384 		if (v6stat.total != v6stat.zero_pos)
1385 			memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
1386 			    v6stat.tmp + v6stat.zero_pos,
1387 			    v6stat.total - v6stat.zero_pos);
1388 	} else
1389 		memcpy(v6, v6stat.tmp, 16);
1390 
1391 	return 1;
1392 }
1393 
1394 static int
1395 ipv6_cb(const char *elem, int len, void *usr)
1396 {
1397 	IPV6_STAT *s = usr;
1398 
1399 	/* Error if 16 bytes written */
1400 	if (s->total == 16)
1401 		return 0;
1402 	if (len == 0) {
1403 		/* Zero length element, corresponds to '::' */
1404 		if (s->zero_pos == -1)
1405 			s->zero_pos = s->total;
1406 		/* If we've already got a :: its an error */
1407 		else if (s->zero_pos != s->total)
1408 			return 0;
1409 		s->zero_cnt++;
1410 	} else {
1411 		/* If more than 4 characters could be final a.b.c.d form */
1412 		if (len > 4) {
1413 			/* Need at least 4 bytes left */
1414 			if (s->total > 12)
1415 				return 0;
1416 			/* Must be end of string */
1417 			if (elem[len])
1418 				return 0;
1419 			if (!ipv4_from_asc(s->tmp + s->total, elem))
1420 				return 0;
1421 			s->total += 4;
1422 		} else {
1423 			if (!ipv6_hex(s->tmp + s->total, elem, len))
1424 				return 0;
1425 			s->total += 2;
1426 		}
1427 	}
1428 	return 1;
1429 }
1430 
1431 /* Convert a string of up to 4 hex digits into the corresponding
1432  * IPv6 form.
1433  */
1434 
1435 static int
1436 ipv6_hex(unsigned char *out, const char *in, int inlen)
1437 {
1438 	unsigned char c;
1439 	unsigned int num = 0;
1440 
1441 	if (inlen > 4)
1442 		return 0;
1443 	while (inlen--) {
1444 		c = *in++;
1445 		num <<= 4;
1446 		if ((c >= '0') && (c <= '9'))
1447 			num |= c - '0';
1448 		else if ((c >= 'A') && (c <= 'F'))
1449 			num |= c - 'A' + 10;
1450 		else if ((c >= 'a') && (c <= 'f'))
1451 			num |=  c - 'a' + 10;
1452 		else
1453 			return 0;
1454 	}
1455 	out[0] = num >> 8;
1456 	out[1] = num & 0xff;
1457 	return 1;
1458 }
1459 
1460 int
1461 X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
1462     unsigned long chtype)
1463 {
1464 	CONF_VALUE *v;
1465 	int i, mval;
1466 	char *p, *type;
1467 
1468 	if (!nm)
1469 		return 0;
1470 
1471 	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1472 		v = sk_CONF_VALUE_value(dn_sk, i);
1473 		type = v->name;
1474 		/* Skip past any leading X. X: X, etc to allow for
1475 		 * multiple instances
1476 		 */
1477 		for (p = type; *p; p++)
1478 			if ((*p == ':') || (*p == ',') || (*p == '.')) {
1479 				p++;
1480 				if (*p)
1481 					type = p;
1482 				break;
1483 			}
1484 		if (*type == '+') {
1485 			mval = -1;
1486 			type++;
1487 		} else
1488 			mval = 0;
1489 		if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
1490 		    (unsigned char *) v->value, -1, -1, mval))
1491 			return 0;
1492 	}
1493 	return 1;
1494 }
1495 LCRYPTO_ALIAS(X509V3_NAME_from_section);
1496