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