xref: /titanic_51/usr/src/common/net/wanboot/auxutil.c (revision 70f9559bd0c02885d84a425eaafc8c280df10efb)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * ====================================================================
37c478bd9Sstevel@tonic-gate  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
67c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
77c478bd9Sstevel@tonic-gate  * are met:
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
107c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
137c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
147c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
157c478bd9Sstevel@tonic-gate  *    distribution.
167c478bd9Sstevel@tonic-gate  *
177c478bd9Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
187c478bd9Sstevel@tonic-gate  *    software must display the following acknowledgment:
197c478bd9Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
207c478bd9Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
217c478bd9Sstevel@tonic-gate  *
227c478bd9Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
237c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
247c478bd9Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
257c478bd9Sstevel@tonic-gate  *    licensing@OpenSSL.org.
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
287c478bd9Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
297c478bd9Sstevel@tonic-gate  *    permission of the OpenSSL Project.
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
327c478bd9Sstevel@tonic-gate  *    acknowledgment:
337c478bd9Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
347c478bd9Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
377c478bd9Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
387c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
397c478bd9Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
407c478bd9Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
417c478bd9Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
427c478bd9Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
437c478bd9Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
447c478bd9Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
457c478bd9Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
467c478bd9Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
477c478bd9Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
487c478bd9Sstevel@tonic-gate  * ====================================================================
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
517c478bd9Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
527c478bd9Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate  * Copyright 2002, 2003 Sun Microsystems, Inc.  All rights reserved.
587c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  * All of the functions included here are internal to the pkcs12 functions
617c478bd9Sstevel@tonic-gate  * in this library.  None of these are exposed.
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate 
64*70f9559bSTheo Schlossnagle /*
65*70f9559bSTheo Schlossnagle  * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
66*70f9559bSTheo Schlossnagle  */
67*70f9559bSTheo Schlossnagle 
687c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #include <stdio.h>
717c478bd9Sstevel@tonic-gate #include <string.h>
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #include <openssl/crypto.h>
747c478bd9Sstevel@tonic-gate #include <openssl/err.h>
757c478bd9Sstevel@tonic-gate #include <openssl/x509.h>
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate #include <openssl/pkcs12.h>
787c478bd9Sstevel@tonic-gate #include <p12aux.h>
797c478bd9Sstevel@tonic-gate #include <auxutil.h>
807c478bd9Sstevel@tonic-gate #include <p12err.h>
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * asc2bmpstring - Convert a regular C ASCII string to an ASn1_STRING in
847c478bd9Sstevel@tonic-gate  *         ASN1_BMPSTRING format.
857c478bd9Sstevel@tonic-gate  *
867c478bd9Sstevel@tonic-gate  * Arguments:
877c478bd9Sstevel@tonic-gate  *   str      - String to be convered.
887c478bd9Sstevel@tonic-gate  *   len      - Length of the string.
897c478bd9Sstevel@tonic-gate  *
907c478bd9Sstevel@tonic-gate  * Returns:
917c478bd9Sstevel@tonic-gate  *   == NULL  - An error occurred.  Error information (accessible by
927c478bd9Sstevel@tonic-gate  *              ERR_get_error()) is set.
937c478bd9Sstevel@tonic-gate  *   != NULL  - Points to an ASN1_BMPSTRING structure with the converted
947c478bd9Sstevel@tonic-gate  *              string as a value.
957c478bd9Sstevel@tonic-gate  */
967c478bd9Sstevel@tonic-gate ASN1_BMPSTRING *
977c478bd9Sstevel@tonic-gate asc2bmpstring(const char *str, int len)
987c478bd9Sstevel@tonic-gate {
997c478bd9Sstevel@tonic-gate 	ASN1_BMPSTRING *bmp = NULL;
1007c478bd9Sstevel@tonic-gate 	uchar_t *uni = NULL;
1017c478bd9Sstevel@tonic-gate 	int unilen;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	/* Convert the character to the bmp format. */
104*70f9559bSTheo Schlossnagle #if OPENSSL_VERSION_NUMBER < 0x10000000L
1057c478bd9Sstevel@tonic-gate 	if (asc2uni(str, len, &uni, &unilen) == 0) {
106*70f9559bSTheo Schlossnagle #else
107*70f9559bSTheo Schlossnagle 	if (OPENSSL_asc2uni(str, len, &uni, &unilen) == 0) {
108*70f9559bSTheo Schlossnagle #endif
1097c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
1107c478bd9Sstevel@tonic-gate 		return (NULL);
1117c478bd9Sstevel@tonic-gate 	}
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	/*
1147c478bd9Sstevel@tonic-gate 	 * Adjust for possible pair of NULL bytes at the end because
1157c478bd9Sstevel@tonic-gate 	 * asc2uni() returns a doubly null terminated string.
1167c478bd9Sstevel@tonic-gate 	 */
1177c478bd9Sstevel@tonic-gate 	if (uni[unilen - 1] == '\0' && uni[unilen - 2] == '\0')
1187c478bd9Sstevel@tonic-gate 		unilen -= 2;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	/* Construct comparison string with correct format */
1217c478bd9Sstevel@tonic-gate 	bmp = M_ASN1_BMPSTRING_new();
1227c478bd9Sstevel@tonic-gate 	if (bmp == NULL) {
1237c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
1247c478bd9Sstevel@tonic-gate 		OPENSSL_free(uni);
1257c478bd9Sstevel@tonic-gate 		return (NULL);
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	bmp->data = uni;
1297c478bd9Sstevel@tonic-gate 	bmp->length = unilen;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	return (bmp);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate /*
1357c478bd9Sstevel@tonic-gate  * utf82ascstr - Convert a UTF8STRING string to a regular C ASCII string.
1367c478bd9Sstevel@tonic-gate  *         This goes through an intermediate step with a ASN1_STRING type of
1377c478bd9Sstevel@tonic-gate  *         IA5STRING (International Alphabet 5, which is the same as ASCII).
1387c478bd9Sstevel@tonic-gate  *
1397c478bd9Sstevel@tonic-gate  * Arguments:
1407c478bd9Sstevel@tonic-gate  *   str      - UTF8STRING to be converted.
1417c478bd9Sstevel@tonic-gate  *
1427c478bd9Sstevel@tonic-gate  * Returns:
1437c478bd9Sstevel@tonic-gate  *   == NULL  - An error occurred.  Error information (accessible by
1447c478bd9Sstevel@tonic-gate  *              ERR_get_error()) is set.
1457c478bd9Sstevel@tonic-gate  *   != NULL  - Points to a NULL-termianted ASCII string.  The caller must
1467c478bd9Sstevel@tonic-gate  *              free it.
1477c478bd9Sstevel@tonic-gate  */
1487c478bd9Sstevel@tonic-gate uchar_t *
1497c478bd9Sstevel@tonic-gate utf82ascstr(ASN1_UTF8STRING *ustr)
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate 	ASN1_STRING tmpstr;
1527c478bd9Sstevel@tonic-gate 	ASN1_STRING *astr = &tmpstr;
1537c478bd9Sstevel@tonic-gate 	uchar_t *retstr = NULL;
1547c478bd9Sstevel@tonic-gate 	int mbflag;
1557c478bd9Sstevel@tonic-gate 	int ret;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	if (ustr == NULL || ustr->type != V_ASN1_UTF8STRING) {
1587c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_INVALID_ARG);
1597c478bd9Sstevel@tonic-gate 		return (NULL);
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	mbflag = MBSTRING_ASC;
1637c478bd9Sstevel@tonic-gate 	tmpstr.data = NULL;
1647c478bd9Sstevel@tonic-gate 	tmpstr.length = 0;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	ret = ASN1_mbstring_copy(&astr, ustr->data, ustr->length, mbflag,
1677c478bd9Sstevel@tonic-gate 	    B_ASN1_IA5STRING);
1687c478bd9Sstevel@tonic-gate 	if (ret < 0) {
1697c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_STR_CONVERT_ERR);
1707c478bd9Sstevel@tonic-gate 		return (NULL);
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	retstr = OPENSSL_malloc(astr->length + 1);
1747c478bd9Sstevel@tonic-gate 	if (retstr == NULL) {
1757c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_MEMORY_FAILURE);
1767c478bd9Sstevel@tonic-gate 		return (NULL);
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	(void) memcpy(retstr, astr->data, astr->length);
1807c478bd9Sstevel@tonic-gate 	retstr[astr->length] = '\0';
1817c478bd9Sstevel@tonic-gate 	OPENSSL_free(astr->data);
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	return (retstr);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate  * set_results - Given two pointers to stacks of private keys, certs or CA
1887c478bd9Sstevel@tonic-gate  *     CA certs, either copy the second stack to the first, or append the
1897c478bd9Sstevel@tonic-gate  *     contents of the second to the first.
1907c478bd9Sstevel@tonic-gate  *
1917c478bd9Sstevel@tonic-gate  * Arguments:
1927c478bd9Sstevel@tonic-gate  *   pkeys    - Points to stack of pkeys
1937c478bd9Sstevel@tonic-gate  *   work_kl  - Points to working stack of pkeys
1947c478bd9Sstevel@tonic-gate  *   certs    - Points to stack of certs
1957c478bd9Sstevel@tonic-gate  *   work_cl  - Points to working stack of certs
1967c478bd9Sstevel@tonic-gate  *   cacerts  - Points to stack of CA certs
1977c478bd9Sstevel@tonic-gate  *   work_ca  - Points to working stack of CA certs
1987c478bd9Sstevel@tonic-gate  *   xtrakeys - Points to stack of unmatcned pkeys
1997c478bd9Sstevel@tonic-gate  *   work_xl  - Points to working stack of unmatcned pkeys
2007c478bd9Sstevel@tonic-gate  *
2017c478bd9Sstevel@tonic-gate  *   The arguments are in pairs.  The first of each pair points to a stack
2027c478bd9Sstevel@tonic-gate  *   of keys or certs.  The second of the pair points at a 'working stack'
2037c478bd9Sstevel@tonic-gate  *   of the same type of entities.   Actions taken are as follows:
2047c478bd9Sstevel@tonic-gate  *
2057c478bd9Sstevel@tonic-gate  *   - If either the first or second argument is NULL, or if there are no
2067c478bd9Sstevel@tonic-gate  *     members in the second stack, there is nothing to do.
2077c478bd9Sstevel@tonic-gate  *   - If the first argument points to a pointer which is NULL, then there
2087c478bd9Sstevel@tonic-gate  *     is no existing stack for the first argument.  Copy the stack pointer
2097c478bd9Sstevel@tonic-gate  *     from the second argument to the first argument and NULL out the stack
2107c478bd9Sstevel@tonic-gate  *     pointer for the second.
2117c478bd9Sstevel@tonic-gate  *   - Otherwise, go through the elements of the second stack, removing each
2127c478bd9Sstevel@tonic-gate  *     and adding it to the first stack.
2137c478bd9Sstevel@tonic-gate  *
2147c478bd9Sstevel@tonic-gate  * Returns:
2157c478bd9Sstevel@tonic-gate  *   == -1 - An error occurred.  Call ERR_get_error() to get error information.
2167c478bd9Sstevel@tonic-gate  *   == 0  - No matching returns were found.
2177c478bd9Sstevel@tonic-gate  *    > 0  - This is the arithmetic 'or' of the FOUND_* bits that indicate which
2187c478bd9Sstevel@tonic-gate  *           of the requested entries were manipulated.
2197c478bd9Sstevel@tonic-gate  */
2207c478bd9Sstevel@tonic-gate int
2217c478bd9Sstevel@tonic-gate set_results(STACK_OF(EVP_PKEY) **pkeys, STACK_OF(EVP_PKEY) **work_kl,
2227c478bd9Sstevel@tonic-gate     STACK_OF(X509) **certs, STACK_OF(X509) **work_cl,
2237c478bd9Sstevel@tonic-gate     STACK_OF(X509) **cacerts, STACK_OF(X509) **work_ca,
2247c478bd9Sstevel@tonic-gate     STACK_OF(EVP_PKEY) **xtrakeys, STACK_OF(EVP_PKEY) **work_xl)
2257c478bd9Sstevel@tonic-gate {
2267c478bd9Sstevel@tonic-gate 	int retval = 0;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	if (pkeys != NULL && work_kl != NULL && *work_kl != NULL &&
2297c478bd9Sstevel@tonic-gate 	    sk_EVP_PKEY_num(*work_kl) > 0) {
2307c478bd9Sstevel@tonic-gate 		if (*pkeys == NULL) {
2317c478bd9Sstevel@tonic-gate 			*pkeys = *work_kl;
2327c478bd9Sstevel@tonic-gate 			*work_kl = NULL;
2337c478bd9Sstevel@tonic-gate 		} else {
2347c478bd9Sstevel@tonic-gate 			if (sunw_append_keys(*pkeys, *work_kl) < 0) {
2357c478bd9Sstevel@tonic-gate 				return (-1);
2367c478bd9Sstevel@tonic-gate 			}
2377c478bd9Sstevel@tonic-gate 		}
2387c478bd9Sstevel@tonic-gate 		retval |= FOUND_PKEY;
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 	if (certs != NULL && work_cl != NULL && *work_cl != NULL &&
2417c478bd9Sstevel@tonic-gate 	    sk_X509_num(*work_cl) > 0) {
2427c478bd9Sstevel@tonic-gate 		if (*certs == NULL) {
2437c478bd9Sstevel@tonic-gate 			*certs = *work_cl;
2447c478bd9Sstevel@tonic-gate 			*work_cl = NULL;
2457c478bd9Sstevel@tonic-gate 		} else {
2467c478bd9Sstevel@tonic-gate 			if (move_certs(*certs, *work_cl) < 0) {
2477c478bd9Sstevel@tonic-gate 				return (-1);
2487c478bd9Sstevel@tonic-gate 			}
2497c478bd9Sstevel@tonic-gate 		}
2507c478bd9Sstevel@tonic-gate 		retval |= FOUND_CERT;
2517c478bd9Sstevel@tonic-gate 	}
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	if (cacerts != NULL && work_ca != NULL && *work_ca != NULL &&
2547c478bd9Sstevel@tonic-gate 	    sk_X509_num(*work_ca) > 0) {
2557c478bd9Sstevel@tonic-gate 		if (*cacerts == NULL) {
2567c478bd9Sstevel@tonic-gate 			*cacerts = *work_ca;
2577c478bd9Sstevel@tonic-gate 			*work_ca = NULL;
2587c478bd9Sstevel@tonic-gate 		} else {
2597c478bd9Sstevel@tonic-gate 			if (move_certs(*cacerts, *work_ca) < 0) {
2607c478bd9Sstevel@tonic-gate 				return (-1);
2617c478bd9Sstevel@tonic-gate 			}
2627c478bd9Sstevel@tonic-gate 		}
2637c478bd9Sstevel@tonic-gate 		retval |= FOUND_CA_CERTS;
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	if (xtrakeys != NULL && work_xl != NULL && *work_xl != NULL &&
2677c478bd9Sstevel@tonic-gate 	    sk_EVP_PKEY_num(*work_xl) > 0) {
2687c478bd9Sstevel@tonic-gate 		if (*xtrakeys == NULL) {
2697c478bd9Sstevel@tonic-gate 			*xtrakeys = *work_xl;
2707c478bd9Sstevel@tonic-gate 			*work_xl = NULL;
2717c478bd9Sstevel@tonic-gate 		} else {
2727c478bd9Sstevel@tonic-gate 			if (sunw_append_keys(*xtrakeys, *work_xl) < 0) {
2737c478bd9Sstevel@tonic-gate 				return (-1);
2747c478bd9Sstevel@tonic-gate 			}
2757c478bd9Sstevel@tonic-gate 		}
2767c478bd9Sstevel@tonic-gate 		retval |= FOUND_XPKEY;
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	return (retval);
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate /*
2837c478bd9Sstevel@tonic-gate  * find_attr - Look for a given attribute of the type associated with the NID.
2847c478bd9Sstevel@tonic-gate  *
2857c478bd9Sstevel@tonic-gate  * Arguments:
2867c478bd9Sstevel@tonic-gate  *   nid      - NID for the attribute to be found (either NID_friendlyName or
2877c478bd9Sstevel@tonic-gate  *              NID_locakKeyId)
2887c478bd9Sstevel@tonic-gate  *   str      - ASN1_STRING-type structure containing the value to be found,
2897c478bd9Sstevel@tonic-gate  *              FriendlyName expects a ASN1_BMPSTRING and localKeyID uses a
2907c478bd9Sstevel@tonic-gate  *              ASN1_STRING.
2917c478bd9Sstevel@tonic-gate  *   kl       - Points to a stack of private keys.
2927c478bd9Sstevel@tonic-gate  *   pkey     - Points at a location where the address of the matching private
2937c478bd9Sstevel@tonic-gate  *              key will be stored.
2947c478bd9Sstevel@tonic-gate  *   cl       - Points to a stack of client certs with matching private keys.
2957c478bd9Sstevel@tonic-gate  *   cert     - Points to locaiton where the address of the matching client cert
2967c478bd9Sstevel@tonic-gate  *              will be returned
2977c478bd9Sstevel@tonic-gate  *
2987c478bd9Sstevel@tonic-gate  * This function is designed to process lists of certs and private keys.
2997c478bd9Sstevel@tonic-gate  * This is made complex because these the attributes are stored differently
3007c478bd9Sstevel@tonic-gate  * for certs and for keys.  For certs, only a few attributes are retained.
3017c478bd9Sstevel@tonic-gate  * FriendlyName is stored in the aux structure, under the name 'alias'.
3027c478bd9Sstevel@tonic-gate  * LocalKeyId is also stored in the aux structure, under the name 'keyid'.
3037c478bd9Sstevel@tonic-gate  * A pkey structure has a stack of attributes.
3047c478bd9Sstevel@tonic-gate  *
3057c478bd9Sstevel@tonic-gate  * The basic approach is:
3067c478bd9Sstevel@tonic-gate  *   - If there there is no stack of certs but a stack of private keys exists,
3077c478bd9Sstevel@tonic-gate  *     search the stack of keys for a match. Alternately, if there is a stack
3087c478bd9Sstevel@tonic-gate  *     of certs and no private keys, search the certs.
3097c478bd9Sstevel@tonic-gate  *
3107c478bd9Sstevel@tonic-gate  *   - If there are both certs and keys, assume that the matching certs and
3117c478bd9Sstevel@tonic-gate  *     keys are in their respective stacks, with matching entries in the same
3127c478bd9Sstevel@tonic-gate  *     order.  Search for the name or keyid in the stack of certs.  If it is
3137c478bd9Sstevel@tonic-gate  *     not found, then this function returns 0 (nothing found).
3147c478bd9Sstevel@tonic-gate  *
3157c478bd9Sstevel@tonic-gate  *   - Once a cert is found, verify that the key actually matches by
3167c478bd9Sstevel@tonic-gate  *     comparing the private key with the public key (in the cert).
3177c478bd9Sstevel@tonic-gate  *     If they don't match, return an error.
3187c478bd9Sstevel@tonic-gate  *
3197c478bd9Sstevel@tonic-gate  *   A pointer to cert and/or pkey which matches the name or keyid is stored
3207c478bd9Sstevel@tonic-gate  *   in the return arguments.
3217c478bd9Sstevel@tonic-gate  *
3227c478bd9Sstevel@tonic-gate  * Returns:
3237c478bd9Sstevel@tonic-gate  *     0 - No matches were found.
3247c478bd9Sstevel@tonic-gate  *   > 0 - Bits set based on FOUND_* definitions, indicating what was found.
3257c478bd9Sstevel@tonic-gate  *         This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
3267c478bd9Sstevel@tonic-gate  */
3277c478bd9Sstevel@tonic-gate int
3287c478bd9Sstevel@tonic-gate find_attr(int nid, ASN1_STRING *str, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey,
3297c478bd9Sstevel@tonic-gate     STACK_OF(X509) *cl, X509 **cert)
3307c478bd9Sstevel@tonic-gate {
3317c478bd9Sstevel@tonic-gate 	ASN1_UTF8STRING *ustr = NULL;
3327c478bd9Sstevel@tonic-gate 	ASN1_STRING *s;
3337c478bd9Sstevel@tonic-gate 	ASN1_TYPE *t;
3347c478bd9Sstevel@tonic-gate 	EVP_PKEY *p;
3357c478bd9Sstevel@tonic-gate 	uchar_t *fname = NULL;
3367c478bd9Sstevel@tonic-gate 	X509 *x;
3377c478bd9Sstevel@tonic-gate 	int found = 0;
3387c478bd9Sstevel@tonic-gate 	int chkcerts;
3397c478bd9Sstevel@tonic-gate 	int len;
3407c478bd9Sstevel@tonic-gate 	int res;
3417c478bd9Sstevel@tonic-gate 	int c = -1;
3427c478bd9Sstevel@tonic-gate 	int k = -1;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	chkcerts = (cert != NULL || pkey != NULL) && cl != NULL;
3457c478bd9Sstevel@tonic-gate 	if (chkcerts && nid == NID_friendlyName &&
3467c478bd9Sstevel@tonic-gate 	    str->type == V_ASN1_BMPSTRING) {
3477c478bd9Sstevel@tonic-gate 		ustr = ASN1_UTF8STRING_new();
3487c478bd9Sstevel@tonic-gate 		if (ustr == NULL) {
3497c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
3507c478bd9Sstevel@tonic-gate 			return (0);
3517c478bd9Sstevel@tonic-gate 		}
3527c478bd9Sstevel@tonic-gate 		len = ASN1_STRING_to_UTF8(&fname, str);
3537c478bd9Sstevel@tonic-gate 		if (fname == NULL) {
3547c478bd9Sstevel@tonic-gate 			ASN1_UTF8STRING_free(ustr);
3557c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_FINDATTR, SUNW_R_STR_CONVERT_ERR);
3567c478bd9Sstevel@tonic-gate 			return (0);
3577c478bd9Sstevel@tonic-gate 		}
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 		if (ASN1_STRING_set(ustr, fname, len) == 0) {
3607c478bd9Sstevel@tonic-gate 			ASN1_UTF8STRING_free(ustr);
3617c478bd9Sstevel@tonic-gate 			OPENSSL_free(fname);
3627c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
3637c478bd9Sstevel@tonic-gate 			return (0);
3647c478bd9Sstevel@tonic-gate 		}
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	if (chkcerts) {
3687c478bd9Sstevel@tonic-gate 		for (c = 0; c < sk_X509_num(cl); c++) {
3697c478bd9Sstevel@tonic-gate 			res = -1;
3707c478bd9Sstevel@tonic-gate 			x = sk_X509_value(cl, c);
3717c478bd9Sstevel@tonic-gate 			if (nid == NID_friendlyName && ustr != NULL) {
3727c478bd9Sstevel@tonic-gate 				if (x->aux == NULL || x->aux->alias == NULL)
3737c478bd9Sstevel@tonic-gate 					continue;
3747c478bd9Sstevel@tonic-gate 				s = x->aux->alias;
3757c478bd9Sstevel@tonic-gate 				if (s != NULL && s->type == ustr->type &&
3767c478bd9Sstevel@tonic-gate 				    s->data != NULL) {
3777c478bd9Sstevel@tonic-gate 					res = ASN1_STRING_cmp(s, ustr);
3787c478bd9Sstevel@tonic-gate 				}
3797c478bd9Sstevel@tonic-gate 			} else {
3807c478bd9Sstevel@tonic-gate 				if (x->aux == NULL || x->aux->keyid == NULL)
3817c478bd9Sstevel@tonic-gate 					continue;
3827c478bd9Sstevel@tonic-gate 				s = x->aux->keyid;
3837c478bd9Sstevel@tonic-gate 				if (s != NULL && s->type == str->type &&
3847c478bd9Sstevel@tonic-gate 				    s->data != NULL) {
3857c478bd9Sstevel@tonic-gate 					res = ASN1_STRING_cmp(s, str);
3867c478bd9Sstevel@tonic-gate 				}
3877c478bd9Sstevel@tonic-gate 			}
3887c478bd9Sstevel@tonic-gate 			if (res == 0) {
3897c478bd9Sstevel@tonic-gate 				if (cert != NULL)
3907c478bd9Sstevel@tonic-gate 					*cert = sk_X509_delete(cl, c);
3917c478bd9Sstevel@tonic-gate 				found = FOUND_CERT;
3927c478bd9Sstevel@tonic-gate 				break;
3937c478bd9Sstevel@tonic-gate 			}
3947c478bd9Sstevel@tonic-gate 		}
3957c478bd9Sstevel@tonic-gate 		if (ustr != NULL) {
3967c478bd9Sstevel@tonic-gate 			ASN1_UTF8STRING_free(ustr);
3977c478bd9Sstevel@tonic-gate 			OPENSSL_free(fname);
3987c478bd9Sstevel@tonic-gate 		}
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	if (pkey != NULL && kl != NULL) {
4027c478bd9Sstevel@tonic-gate 		/*
4037c478bd9Sstevel@tonic-gate 		 * Looking for pkey to match a cert?  If so, assume that
4047c478bd9Sstevel@tonic-gate 		 * lists of certs and their matching pkeys are in the same
4057c478bd9Sstevel@tonic-gate 		 * order.  Call X509_check_private_key() to verify this
4067c478bd9Sstevel@tonic-gate 		 * assumption.
4077c478bd9Sstevel@tonic-gate 		 */
4087c478bd9Sstevel@tonic-gate 		if (found != 0 && cert != NULL) {
4097c478bd9Sstevel@tonic-gate 			k = c;
4107c478bd9Sstevel@tonic-gate 			p = sk_EVP_PKEY_value(kl, k);
4117c478bd9Sstevel@tonic-gate 			if (X509_check_private_key(x, p) != 0) {
4127c478bd9Sstevel@tonic-gate 				if (pkey != NULL)
4137c478bd9Sstevel@tonic-gate 					*pkey = sk_EVP_PKEY_delete(kl, k);
4147c478bd9Sstevel@tonic-gate 				found |= FOUND_PKEY;
4157c478bd9Sstevel@tonic-gate 			}
4167c478bd9Sstevel@tonic-gate 		} else if (cert == NULL) {
4177c478bd9Sstevel@tonic-gate 			for (k = 0; k < sk_EVP_PKEY_num(kl); k++) {
4187c478bd9Sstevel@tonic-gate 				p = sk_EVP_PKEY_value(kl, k);
4197c478bd9Sstevel@tonic-gate 				if (p == NULL || p->attributes == NULL)
4207c478bd9Sstevel@tonic-gate 					continue;
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 				t = PKCS12_get_attr_gen(p->attributes, nid);
4237c478bd9Sstevel@tonic-gate 				if (t != NULL || ASN1_STRING_cmp(str,
4247c478bd9Sstevel@tonic-gate 				    t->value.asn1_string) == 0)
4257c478bd9Sstevel@tonic-gate 					continue;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 				found |= FOUND_PKEY;
4287c478bd9Sstevel@tonic-gate 				if (pkey != NULL)
4297c478bd9Sstevel@tonic-gate 					*pkey = sk_EVP_PKEY_delete(kl, k);
4307c478bd9Sstevel@tonic-gate 				break;
4317c478bd9Sstevel@tonic-gate 			}
4327c478bd9Sstevel@tonic-gate 		}
4337c478bd9Sstevel@tonic-gate 	}
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	return (found);
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate /*
4397c478bd9Sstevel@tonic-gate  * find_attr_by_nid - Given a ASN1_TYPE, return the offset of a X509_ATTRIBUTE
4407c478bd9Sstevel@tonic-gate  *     of the type specified by the given NID.
4417c478bd9Sstevel@tonic-gate  *
4427c478bd9Sstevel@tonic-gate  * Arguments:
4437c478bd9Sstevel@tonic-gate  *   attrs    - Stack of attributes to search
4447c478bd9Sstevel@tonic-gate  *   nid      - NID of the attribute being searched for
4457c478bd9Sstevel@tonic-gate  *
4467c478bd9Sstevel@tonic-gate  * Returns:
4477c478bd9Sstevel@tonic-gate  *   -1 	None found
4487c478bd9Sstevel@tonic-gate  *   != -1	Offset of the matching attribute.
4497c478bd9Sstevel@tonic-gate  */
4507c478bd9Sstevel@tonic-gate int
4517c478bd9Sstevel@tonic-gate find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	X509_ATTRIBUTE *a;
4547c478bd9Sstevel@tonic-gate 	int i;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	if (attrs == NULL)
4577c478bd9Sstevel@tonic-gate 		return (-1);
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4607c478bd9Sstevel@tonic-gate 		a = sk_X509_ATTRIBUTE_value(attrs, i);
4617c478bd9Sstevel@tonic-gate 		if (OBJ_obj2nid(a->object) == nid)
4627c478bd9Sstevel@tonic-gate 			return (i);
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 	return (-1);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate /*
4687c478bd9Sstevel@tonic-gate  * get_key_cert - Get a cert and its matching key from the stacks of certs
4697c478bd9Sstevel@tonic-gate  *      and keys.  They are removed from the stacks.
4707c478bd9Sstevel@tonic-gate  *
4717c478bd9Sstevel@tonic-gate  * Arguments:
4727c478bd9Sstevel@tonic-gate  *   n        - Offset of the entries to return.
4737c478bd9Sstevel@tonic-gate  *   kl       - Points to a stack of private keys that matches the list of
4747c478bd9Sstevel@tonic-gate  *              certs below.
4757c478bd9Sstevel@tonic-gate  *   pkey     - Points at location where the address of the matching private
4767c478bd9Sstevel@tonic-gate  *              key will be stored.
4777c478bd9Sstevel@tonic-gate  *   cl       - Points to a stack of client certs with matching private keys.
4787c478bd9Sstevel@tonic-gate  *   cert     - Points to locaiton where the address of the matching client cert
4797c478bd9Sstevel@tonic-gate  *              will be returned
4807c478bd9Sstevel@tonic-gate  *
4817c478bd9Sstevel@tonic-gate  * The assumption is that the stacks of keys and certs contain key/cert pairs,
4827c478bd9Sstevel@tonic-gate  * with entries in the same order and hence at the same offset.  Provided
4837c478bd9Sstevel@tonic-gate  * the key and cert selected match, each will be removed from its stack and
4847c478bd9Sstevel@tonic-gate  * returned.
4857c478bd9Sstevel@tonic-gate  *
4867c478bd9Sstevel@tonic-gate  * A stack of certs can be passed in without a stack of private keys, and vise
4877c478bd9Sstevel@tonic-gate  * versa.  In that case, the indicated key/cert will be returned.
4887c478bd9Sstevel@tonic-gate  *
4897c478bd9Sstevel@tonic-gate  * Returns:
4907c478bd9Sstevel@tonic-gate  *     0 - No matches were found.
4917c478bd9Sstevel@tonic-gate  *   > 0 - Bits set based on FOUND_* definitions, indicating what is returned.
4927c478bd9Sstevel@tonic-gate  *         This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
4937c478bd9Sstevel@tonic-gate  */
4947c478bd9Sstevel@tonic-gate int
4957c478bd9Sstevel@tonic-gate get_key_cert(int n, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey, STACK_OF(X509) *cl,
4967c478bd9Sstevel@tonic-gate     X509 **cert)
4977c478bd9Sstevel@tonic-gate {
4987c478bd9Sstevel@tonic-gate 	int retval = 0;
4997c478bd9Sstevel@tonic-gate 	int nk;
5007c478bd9Sstevel@tonic-gate 	int nc;
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	nk = (kl != NULL) ? sk_EVP_PKEY_num(kl) : 0;
5037c478bd9Sstevel@tonic-gate 	nc = (cl != NULL) ? sk_X509_num(cl) : 0;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	if (pkey != NULL && *pkey == NULL) {
5067c478bd9Sstevel@tonic-gate 		if (nk > 0 && n >= 0 || n < nk) {
5077c478bd9Sstevel@tonic-gate 			*pkey = sk_EVP_PKEY_delete(kl, n);
5087c478bd9Sstevel@tonic-gate 			if (*pkey != NULL)
5097c478bd9Sstevel@tonic-gate 				retval |= FOUND_PKEY;
5107c478bd9Sstevel@tonic-gate 		}
5117c478bd9Sstevel@tonic-gate 	}
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	if (cert != NULL && *cert == NULL) {
5147c478bd9Sstevel@tonic-gate 		if (nc > 0 && n >= 0 && n < nc) {
5157c478bd9Sstevel@tonic-gate 			*cert = sk_X509_delete(cl, n);
5167c478bd9Sstevel@tonic-gate 			if (*cert != NULL)
5177c478bd9Sstevel@tonic-gate 				retval |= FOUND_CERT;
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	return (retval);
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate /*
5257c478bd9Sstevel@tonic-gate  * type2attrib - Given a ASN1_TYPE, return a X509_ATTRIBUTE of the type
5267c478bd9Sstevel@tonic-gate  *     specified by the given NID.
5277c478bd9Sstevel@tonic-gate  *
5287c478bd9Sstevel@tonic-gate  * Arguments:
5297c478bd9Sstevel@tonic-gate  *   ty       - Type structure to be made into an attribute
5307c478bd9Sstevel@tonic-gate  *   nid      - NID of the attribute
5317c478bd9Sstevel@tonic-gate  *
5327c478bd9Sstevel@tonic-gate  * Returns:
5337c478bd9Sstevel@tonic-gate  *   NULL	An error occurred.
5347c478bd9Sstevel@tonic-gate  *   != NULL	An X509_ATTRIBUTE structure.
5357c478bd9Sstevel@tonic-gate  */
5367c478bd9Sstevel@tonic-gate X509_ATTRIBUTE *
5377c478bd9Sstevel@tonic-gate type2attrib(ASN1_TYPE *ty, int nid)
5387c478bd9Sstevel@tonic-gate {
5397c478bd9Sstevel@tonic-gate 	X509_ATTRIBUTE *a;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if ((a = X509_ATTRIBUTE_new()) == NULL ||
5427c478bd9Sstevel@tonic-gate 	    (a->value.set = sk_ASN1_TYPE_new_null()) == NULL ||
5437c478bd9Sstevel@tonic-gate 	    sk_ASN1_TYPE_push(a->value.set, ty) == 0) {
5447c478bd9Sstevel@tonic-gate 		if (a != NULL)
5457c478bd9Sstevel@tonic-gate 			X509_ATTRIBUTE_free(a);
5467c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_TYPE2ATTRIB, SUNW_R_MEMORY_FAILURE);
5477c478bd9Sstevel@tonic-gate 		return (NULL);
5487c478bd9Sstevel@tonic-gate 	}
5497c478bd9Sstevel@tonic-gate 	a->single = 0;
5507c478bd9Sstevel@tonic-gate 	a->object = OBJ_nid2obj(nid);
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	return (a);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate /*
5567c478bd9Sstevel@tonic-gate  * attrib2type - Given a X509_ATTRIBUTE, return pointer to the ASN1_TYPE
5577c478bd9Sstevel@tonic-gate  *     component
5587c478bd9Sstevel@tonic-gate  *
5597c478bd9Sstevel@tonic-gate  * Arguments:
5607c478bd9Sstevel@tonic-gate  *   attr     - Attribute structure containing a type.
5617c478bd9Sstevel@tonic-gate  *
5627c478bd9Sstevel@tonic-gate  * Returns:
5637c478bd9Sstevel@tonic-gate  *   NULL	An error occurred.
5647c478bd9Sstevel@tonic-gate  *   != NULL	An ASN1_TYPE structure.
5657c478bd9Sstevel@tonic-gate  */
5667c478bd9Sstevel@tonic-gate ASN1_TYPE *
5677c478bd9Sstevel@tonic-gate attrib2type(X509_ATTRIBUTE *attr)
5687c478bd9Sstevel@tonic-gate {
5697c478bd9Sstevel@tonic-gate 	ASN1_TYPE *ty = NULL;
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	if (attr == NULL || attr->single == 1)
5727c478bd9Sstevel@tonic-gate 		return (NULL);
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	if (sk_ASN1_TYPE_num(attr->value.set) > 0)
5757c478bd9Sstevel@tonic-gate 		ty = sk_ASN1_TYPE_value(attr->value.set, 0);
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	return (ty);
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate /*
5817c478bd9Sstevel@tonic-gate  * move_certs - Given two stacks of certs, remove the certs from
5827c478bd9Sstevel@tonic-gate  *      the second stack and append them to the first.
5837c478bd9Sstevel@tonic-gate  *
5847c478bd9Sstevel@tonic-gate  * Arguments:
5857c478bd9Sstevel@tonic-gate  *   dst 	- the stack to receive the certs from 'src'
5867c478bd9Sstevel@tonic-gate  *   src	- the stack whose certs are to be moved.
5877c478bd9Sstevel@tonic-gate  *
5887c478bd9Sstevel@tonic-gate  * Returns:
5897c478bd9Sstevel@tonic-gate  *   -1  	- An error occurred.  The error status is set.
5907c478bd9Sstevel@tonic-gate  *   >= 0       - The number of certs that were copied.
5917c478bd9Sstevel@tonic-gate  */
5927c478bd9Sstevel@tonic-gate int
5937c478bd9Sstevel@tonic-gate move_certs(STACK_OF(X509) *dst, STACK_OF(X509) *src)
5947c478bd9Sstevel@tonic-gate {
5957c478bd9Sstevel@tonic-gate 	X509 *tmpc;
5967c478bd9Sstevel@tonic-gate 	int count = 0;
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	while (sk_X509_num(src) > 0) {
5997c478bd9Sstevel@tonic-gate 		tmpc = sk_X509_delete(src, 0);
6007c478bd9Sstevel@tonic-gate 		if (sk_X509_push(dst, tmpc) == 0) {
6017c478bd9Sstevel@tonic-gate 			X509_free(tmpc);
6027c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_MOVE_CERTS, SUNW_R_MEMORY_FAILURE);
6037c478bd9Sstevel@tonic-gate 			return (-1);
6047c478bd9Sstevel@tonic-gate 		}
6057c478bd9Sstevel@tonic-gate 		count++;
6067c478bd9Sstevel@tonic-gate 	}
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	return (count);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate /*
6127c478bd9Sstevel@tonic-gate  * print_time - Given an ASN1_TIME, print one or both of the times.
6137c478bd9Sstevel@tonic-gate  *
6147c478bd9Sstevel@tonic-gate  * Arguments:
6157c478bd9Sstevel@tonic-gate  *   fp         - File to write to
6167c478bd9Sstevel@tonic-gate  *   t          - The time to format and print.
6177c478bd9Sstevel@tonic-gate  *
6187c478bd9Sstevel@tonic-gate  * Returns:
6197c478bd9Sstevel@tonic-gate  *   0          - Error occurred while opening or writing.
6207c478bd9Sstevel@tonic-gate  *   > 0        - Success.
6217c478bd9Sstevel@tonic-gate  */
6227c478bd9Sstevel@tonic-gate int
6237c478bd9Sstevel@tonic-gate print_time(FILE *fp, ASN1_TIME *t)
6247c478bd9Sstevel@tonic-gate {
6257c478bd9Sstevel@tonic-gate 	BIO *bp;
6267c478bd9Sstevel@tonic-gate 	int ret = 1;
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 	if ((bp = BIO_new(BIO_s_file())) == NULL) {
6297c478bd9Sstevel@tonic-gate 		return (0);
6307c478bd9Sstevel@tonic-gate 	}
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	(void) BIO_set_fp(bp, fp, BIO_NOCLOSE);
6337c478bd9Sstevel@tonic-gate 	ret = ASN1_TIME_print(bp, t);
6347c478bd9Sstevel@tonic-gate 	(void) BIO_free(bp);
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	return (ret);
6377c478bd9Sstevel@tonic-gate }
638