10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51914Scasper  * Common Development and Distribution License (the "License").
61914Scasper  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*10500SHai-May.Chao@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <errno.h>
290Sstevel@tonic-gate #include <strings.h>
300Sstevel@tonic-gate #include <locale.h>
310Sstevel@tonic-gate #include <stdlib.h>
320Sstevel@tonic-gate #include "cryptoutil.h"
330Sstevel@tonic-gate 
340Sstevel@tonic-gate static int uef_interpret(char *, uentry_t **);
350Sstevel@tonic-gate static int parse_policylist(char *, uentry_t *);
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * Retrieve the user-level provider info from the pkcs11.conf file.
390Sstevel@tonic-gate  * If successful, the result is returned from the ppliblist argument.
400Sstevel@tonic-gate  * This function returns SUCCESS if successfully done; otherwise it returns
410Sstevel@tonic-gate  * FAILURE.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate int
440Sstevel@tonic-gate get_pkcs11conf_info(uentrylist_t **ppliblist)
450Sstevel@tonic-gate {
460Sstevel@tonic-gate 	FILE *pfile;
470Sstevel@tonic-gate 	char buffer[BUFSIZ];
480Sstevel@tonic-gate 	size_t len;
490Sstevel@tonic-gate 	uentry_t *pent;
500Sstevel@tonic-gate 	uentrylist_t *pentlist;
510Sstevel@tonic-gate 	uentrylist_t *pcur;
520Sstevel@tonic-gate 	int rc = SUCCESS;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	*ppliblist = NULL;
551914Scasper 	if ((pfile = fopen(_PATH_PKCS11_CONF, "rF")) == NULL) {
560Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_PKCS11_CONF);
570Sstevel@tonic-gate 		return (FAILURE);
580Sstevel@tonic-gate 	}
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
610Sstevel@tonic-gate 		if (buffer[0] == '#' || buffer[0] == ' ' ||
620Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t') {
630Sstevel@tonic-gate 			continue;   /* ignore comment lines */
640Sstevel@tonic-gate 		}
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 		len = strlen(buffer);
670Sstevel@tonic-gate 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
680Sstevel@tonic-gate 			len--;
690Sstevel@tonic-gate 		}
700Sstevel@tonic-gate 		buffer[len] = '\0';
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 		if ((rc = uef_interpret(buffer,  &pent)) != SUCCESS) {
730Sstevel@tonic-gate 			break;
740Sstevel@tonic-gate 		}
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 		/* append pent into ppliblist */
770Sstevel@tonic-gate 		pentlist = malloc(sizeof (uentrylist_t));
780Sstevel@tonic-gate 		if (pentlist == NULL) {
790Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
800Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
810Sstevel@tonic-gate 			free_uentry(pent);
820Sstevel@tonic-gate 			rc = FAILURE;
830Sstevel@tonic-gate 			break;
840Sstevel@tonic-gate 		}
850Sstevel@tonic-gate 		pentlist->puent = pent;
860Sstevel@tonic-gate 		pentlist->next = NULL;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 		if (*ppliblist == NULL) {
890Sstevel@tonic-gate 			*ppliblist = pcur = pentlist;
900Sstevel@tonic-gate 		} else {
910Sstevel@tonic-gate 			pcur->next = pentlist;
920Sstevel@tonic-gate 			pcur = pcur->next;
930Sstevel@tonic-gate 		}
940Sstevel@tonic-gate 	}
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	(void) fclose(pfile);
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	if (rc != SUCCESS) {
990Sstevel@tonic-gate 		free_uentrylist(*ppliblist);
1000Sstevel@tonic-gate 		*ppliblist = NULL;
1010Sstevel@tonic-gate 	}
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 	return (rc);
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate /*
1080Sstevel@tonic-gate  * This routine converts a char string into a uentry_t structure
1090Sstevel@tonic-gate  * The input string "buf" should be one of the following:
1100Sstevel@tonic-gate  *	library_name
1110Sstevel@tonic-gate  *	library_name:NO_RANDOM
1120Sstevel@tonic-gate  *	library_name:disabledlist=m1,m2,...,mk
1130Sstevel@tonic-gate  *	library_name:disabledlist=m1,m2,...,mk;NO_RANDOM
1140Sstevel@tonic-gate  *	library_name:enabledlist=
1150Sstevel@tonic-gate  *	library_name:enabledlist=;NO_RANDOM
1160Sstevel@tonic-gate  *	library_name:enabledlist=m1,m2,...,mk
1170Sstevel@tonic-gate  *	library_name:enabledlist=m1,m2,...,mk;NO_RANDOM
1180Sstevel@tonic-gate  *	metaslot:status=enabled;enabledlist=m1,m2,....;slot=<slot-description>;\
1190Sstevel@tonic-gate  *	token=<token-label>
1200Sstevel@tonic-gate  *
1210Sstevel@tonic-gate  * Note:
1220Sstevel@tonic-gate  *	The mechanisms m1,..mk are in hex form. For example, "0x00000210"
1230Sstevel@tonic-gate  *	for CKM_MD5.
1240Sstevel@tonic-gate  *
1250Sstevel@tonic-gate  *	For the metaslot entry, "enabledlist", "slot", "auto_key_migrate"
1260Sstevel@tonic-gate  * 	or "token" is optional
1270Sstevel@tonic-gate  */
1280Sstevel@tonic-gate static int
1290Sstevel@tonic-gate uef_interpret(char *buf, uentry_t **ppent)
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate 	uentry_t *pent;
1320Sstevel@tonic-gate 	char	*token1;
1330Sstevel@tonic-gate 	char	*token2;
1340Sstevel@tonic-gate 	char	*lasts;
1350Sstevel@tonic-gate 	int	rc;
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	*ppent = NULL;
1380Sstevel@tonic-gate 	if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) {
1390Sstevel@tonic-gate 		/* buf is NULL */
1400Sstevel@tonic-gate 		return (FAILURE);
1410Sstevel@tonic-gate 	};
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	pent = calloc(sizeof (uentry_t), 1);
1440Sstevel@tonic-gate 	if (pent == NULL) {
1450Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
1460Sstevel@tonic-gate 		    _PATH_PKCS11_CONF);
1470Sstevel@tonic-gate 		return (FAILURE);
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 	(void) strlcpy(pent->name, token1, sizeof (pent->name));
1500Sstevel@tonic-gate 	/*
1510Sstevel@tonic-gate 	 * in case metaslot_auto_key_migrate is not specified, it should
1520Sstevel@tonic-gate 	 * be default to true
1530Sstevel@tonic-gate 	 */
1540Sstevel@tonic-gate 	pent->flag_metaslot_auto_key_migrate = B_TRUE;
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	while ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) != NULL) {
1570Sstevel@tonic-gate 		if ((rc = parse_policylist(token2, pent)) != SUCCESS) {
1580Sstevel@tonic-gate 			free_uentry(pent);
1590Sstevel@tonic-gate 			return (rc);
1600Sstevel@tonic-gate 		}
1610Sstevel@tonic-gate 	}
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	*ppent = pent;
1640Sstevel@tonic-gate 	return (SUCCESS);
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate  * This routine parses the policy list and stored the result in the argument
1700Sstevel@tonic-gate  * pent.
1710Sstevel@tonic-gate  *
1720Sstevel@tonic-gate  * 	Arg buf: input only, its format should be one of the following:
1730Sstevel@tonic-gate  *     		enabledlist=
1740Sstevel@tonic-gate  *		enabledlist=m1,m2,...,mk
1750Sstevel@tonic-gate  *		disabledlist=m1,m2,...,mk
1760Sstevel@tonic-gate  *		NO_RANDOM
1770Sstevel@tonic-gate  *		metaslot_status=enabled|disabled
1780Sstevel@tonic-gate  *		metaslot_token=<token-label>
1790Sstevel@tonic-gate  *		metaslot_slot=<slot-description.
1800Sstevel@tonic-gate  *
1810Sstevel@tonic-gate  *	Arg pent: input/output
1820Sstevel@tonic-gate  *
1830Sstevel@tonic-gate  *      return: SUCCESS or FAILURE
1840Sstevel@tonic-gate  */
1850Sstevel@tonic-gate static int
1860Sstevel@tonic-gate parse_policylist(char *buf, uentry_t *pent)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate 	umechlist_t *phead = NULL;
1890Sstevel@tonic-gate 	umechlist_t *pcur = NULL;
1900Sstevel@tonic-gate 	umechlist_t *pmech;
1910Sstevel@tonic-gate 	char *next_token;
1920Sstevel@tonic-gate 	char *value;
1930Sstevel@tonic-gate 	char *lasts;
1940Sstevel@tonic-gate 	int count = 0;
1950Sstevel@tonic-gate 	int rc = SUCCESS;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	if (pent == NULL) {
1980Sstevel@tonic-gate 		return (FAILURE);
1990Sstevel@tonic-gate 	}
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	if (strncmp(buf, EF_DISABLED, sizeof (EF_DISABLED) - 1) == 0) {
2020Sstevel@tonic-gate 		pent->flag_enabledlist = B_FALSE;
2030Sstevel@tonic-gate 	} else if (strncmp(buf, EF_ENABLED, sizeof (EF_ENABLED) - 1) == 0) {
2040Sstevel@tonic-gate 		pent->flag_enabledlist = B_TRUE;
2050Sstevel@tonic-gate 	} else if (strncmp(buf, EF_NORANDOM, sizeof (EF_NORANDOM) - 1) == 0) {
2060Sstevel@tonic-gate 		pent->flag_norandom = B_TRUE;
2070Sstevel@tonic-gate 		return (rc);
2080Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_TOKEN,
2090Sstevel@tonic-gate 	    sizeof (METASLOT_TOKEN) - 1) == 0) {
2100Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2110Sstevel@tonic-gate 			value++; /* get rid of = */
2120Sstevel@tonic-gate 			(void) strlcpy((char *)pent->metaslot_ks_token, value,
2133089Swyllys 			    sizeof (pent->metaslot_ks_token));
2140Sstevel@tonic-gate 			return (SUCCESS);
2150Sstevel@tonic-gate 		} else {
2160Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2170Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2180Sstevel@tonic-gate 			return (FAILURE);
2190Sstevel@tonic-gate 		}
2200Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_SLOT,
2210Sstevel@tonic-gate 	    sizeof (METASLOT_SLOT) - 1) == 0) {
2220Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2230Sstevel@tonic-gate 			value++; /* get rid of = */
2240Sstevel@tonic-gate 			(void) strlcpy((char *)pent->metaslot_ks_slot, value,
2253089Swyllys 			    sizeof (pent->metaslot_ks_slot));
2260Sstevel@tonic-gate 			return (SUCCESS);
2270Sstevel@tonic-gate 		} else {
2280Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2290Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2300Sstevel@tonic-gate 			return (FAILURE);
2310Sstevel@tonic-gate 		}
2320Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_STATUS,
2330Sstevel@tonic-gate 	    sizeof (METASLOT_STATUS) - 1) == 0) {
2340Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2350Sstevel@tonic-gate 			value++; /* get rid of = */
236*10500SHai-May.Chao@Sun.COM 			if (strcmp(value, DISABLED_KEYWORD) == 0) {
2370Sstevel@tonic-gate 				pent->flag_metaslot_enabled = B_FALSE;
238*10500SHai-May.Chao@Sun.COM 			} else if (strcmp(value, ENABLED_KEYWORD) == 0) {
2390Sstevel@tonic-gate 				pent->flag_metaslot_enabled = B_TRUE;
2400Sstevel@tonic-gate 			} else {
2410Sstevel@tonic-gate 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
2420Sstevel@tonic-gate 				    _PATH_PKCS11_CONF);
2430Sstevel@tonic-gate 				return (FAILURE);
2440Sstevel@tonic-gate 			}
2450Sstevel@tonic-gate 			return (SUCCESS);
2460Sstevel@tonic-gate 		} else {
2470Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2480Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2490Sstevel@tonic-gate 			return (FAILURE);
2500Sstevel@tonic-gate 		}
2510Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_AUTO_KEY_MIGRATE,
2520Sstevel@tonic-gate 	    sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) {
2530Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2540Sstevel@tonic-gate 			value++; /* get rid of = */
255*10500SHai-May.Chao@Sun.COM 			if (strcmp(value, DISABLED_KEYWORD) == 0) {
2560Sstevel@tonic-gate 				pent->flag_metaslot_auto_key_migrate = B_FALSE;
257*10500SHai-May.Chao@Sun.COM 			} else if (strcmp(value, ENABLED_KEYWORD) == 0) {
2580Sstevel@tonic-gate 				pent->flag_metaslot_auto_key_migrate = B_TRUE;
2590Sstevel@tonic-gate 			} else {
2600Sstevel@tonic-gate 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
2610Sstevel@tonic-gate 				    _PATH_PKCS11_CONF);
2620Sstevel@tonic-gate 				return (FAILURE);
2630Sstevel@tonic-gate 			}
2640Sstevel@tonic-gate 			return (SUCCESS);
2650Sstevel@tonic-gate 		} else {
2660Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2670Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2680Sstevel@tonic-gate 			return (FAILURE);
2690Sstevel@tonic-gate 		}
2700Sstevel@tonic-gate 	} else {
2710Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to parse %s.\n",
2720Sstevel@tonic-gate 		    _PATH_PKCS11_CONF);
2730Sstevel@tonic-gate 		return (FAILURE);
2740Sstevel@tonic-gate 	}
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	if (value = strpbrk(buf, SEP_EQUAL)) {
2770Sstevel@tonic-gate 		value++; /* get rid of = */
2780Sstevel@tonic-gate 	}
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	if ((next_token = strtok_r(value, SEP_COMMA, &lasts)) == NULL) {
2810Sstevel@tonic-gate 		if (pent->flag_enabledlist) {
2820Sstevel@tonic-gate 			return (SUCCESS);
2830Sstevel@tonic-gate 		} else {
2840Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2850Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2860Sstevel@tonic-gate 			return (FAILURE);
2870Sstevel@tonic-gate 		}
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	while (next_token) {
2910Sstevel@tonic-gate 		if ((pmech = create_umech(next_token)) == NULL) {
2920Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
2930Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2940Sstevel@tonic-gate 			rc = FAILURE;
2950Sstevel@tonic-gate 			break;
2960Sstevel@tonic-gate 		}
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 		if (phead == NULL) {
2990Sstevel@tonic-gate 			phead = pcur = pmech;
3000Sstevel@tonic-gate 		} else {
3010Sstevel@tonic-gate 			pcur->next = pmech;
3020Sstevel@tonic-gate 			pcur = pcur->next;
3030Sstevel@tonic-gate 		}
3040Sstevel@tonic-gate 		count++;
3050Sstevel@tonic-gate 		next_token = strtok_r(NULL, SEP_COMMA, &lasts);
3060Sstevel@tonic-gate 	}
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	if (rc == SUCCESS) {
3090Sstevel@tonic-gate 		pent->policylist = phead;
3100Sstevel@tonic-gate 		pent->count = count;
3110Sstevel@tonic-gate 	} else {
3120Sstevel@tonic-gate 		free_umechlist(phead);
3130Sstevel@tonic-gate 	}
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	return (rc);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate /*
3200Sstevel@tonic-gate  * Create one item of type umechlist_t with the mechanism name.  A NULL is
3210Sstevel@tonic-gate  * returned when the input name is NULL or the heap memory is insufficient.
3220Sstevel@tonic-gate  */
3230Sstevel@tonic-gate umechlist_t *
3240Sstevel@tonic-gate create_umech(char *name)
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate 	umechlist_t *pmech = NULL;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	if (name == NULL) {
3290Sstevel@tonic-gate 		return (NULL);
3300Sstevel@tonic-gate 	}
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	if ((pmech = malloc(sizeof (umechlist_t))) != NULL) {
3330Sstevel@tonic-gate 		(void) strlcpy(pmech->name, name, sizeof (pmech->name));
3340Sstevel@tonic-gate 		pmech->next = NULL;
3350Sstevel@tonic-gate 	}
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	return (pmech);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate void
3420Sstevel@tonic-gate free_umechlist(umechlist_t *plist)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate 	umechlist_t *pnext;
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	while (plist != NULL) {
3470Sstevel@tonic-gate 		pnext = plist->next;
3480Sstevel@tonic-gate 		free(plist);
3490Sstevel@tonic-gate 		plist = pnext;
3500Sstevel@tonic-gate 	}
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate void
3550Sstevel@tonic-gate free_uentry(uentry_t  *pent)
3560Sstevel@tonic-gate {
3570Sstevel@tonic-gate 	if (pent == NULL) {
3580Sstevel@tonic-gate 		return;
3590Sstevel@tonic-gate 	} else {
3600Sstevel@tonic-gate 		free_umechlist(pent->policylist);
3610Sstevel@tonic-gate 		free(pent);
3620Sstevel@tonic-gate 	}
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate void
3670Sstevel@tonic-gate free_uentrylist(uentrylist_t *entrylist)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate 	uentrylist_t *pnext;
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	while (entrylist != NULL) {
3720Sstevel@tonic-gate 		pnext = entrylist->next;
3730Sstevel@tonic-gate 		free_uentry(entrylist->puent);
3740Sstevel@tonic-gate 		free(entrylist);
3750Sstevel@tonic-gate 		entrylist = pnext;
3760Sstevel@tonic-gate 	}
3770Sstevel@tonic-gate }
3783089Swyllys 
3793089Swyllys 
3803089Swyllys 
3813089Swyllys /*
3823089Swyllys  * Duplicate an UEF mechanism list.  A NULL pointer is returned if out of
3833089Swyllys  * memory or the input argument is NULL.
3843089Swyllys  */
3853089Swyllys static umechlist_t *
3863089Swyllys dup_umechlist(umechlist_t *plist)
3873089Swyllys {
3883089Swyllys 	umechlist_t *pres = NULL;
3893089Swyllys 	umechlist_t *pcur;
3903089Swyllys 	umechlist_t *ptmp;
3913089Swyllys 	int rc = SUCCESS;
3923089Swyllys 
3933089Swyllys 	while (plist != NULL) {
3943089Swyllys 		if (!(ptmp = create_umech(plist->name))) {
3953089Swyllys 			rc = FAILURE;
3963089Swyllys 			break;
3973089Swyllys 		}
3983089Swyllys 
3993089Swyllys 		if (pres == NULL) {
4003089Swyllys 			pres = pcur = ptmp;
4013089Swyllys 		} else {
4023089Swyllys 			pcur->next = ptmp;
4033089Swyllys 			pcur = pcur->next;
4043089Swyllys 		}
4053089Swyllys 		plist = plist->next;
4063089Swyllys 	}
4073089Swyllys 
4083089Swyllys 	if (rc != SUCCESS) {
4093089Swyllys 		free_umechlist(pres);
4103089Swyllys 		return (NULL);
4113089Swyllys 	}
4123089Swyllys 
4133089Swyllys 	return (pres);
4143089Swyllys }
4153089Swyllys 
4163089Swyllys 
4173089Swyllys /*
4183089Swyllys  * Duplicate an uentry.  A NULL pointer is returned if out of memory
4193089Swyllys  * or the input argument is NULL.
4203089Swyllys  */
4213089Swyllys static uentry_t *
4223089Swyllys dup_uentry(uentry_t *puent1)
4233089Swyllys {
4243089Swyllys 	uentry_t *puent2 = NULL;
4253089Swyllys 
4263089Swyllys 	if (puent1 == NULL) {
4273089Swyllys 		return (NULL);
4283089Swyllys 	}
4293089Swyllys 
4303089Swyllys 	if ((puent2 = malloc(sizeof (uentry_t))) == NULL) {
4313089Swyllys 		cryptoerror(LOG_STDERR, gettext("out of memory."));
4323089Swyllys 		return (NULL);
4333089Swyllys 	} else {
4343089Swyllys 		(void) strlcpy(puent2->name, puent1->name,
4353089Swyllys 		    sizeof (puent2->name));
4363089Swyllys 		puent2->flag_norandom = puent1->flag_norandom;
4373089Swyllys 		puent2->flag_enabledlist = puent1->flag_enabledlist;
4383089Swyllys 		puent2->policylist = dup_umechlist(puent1->policylist);
4393089Swyllys 		puent2->flag_metaslot_enabled = puent1->flag_metaslot_enabled;
4403089Swyllys 		puent2->flag_metaslot_auto_key_migrate
4413089Swyllys 		    = puent1->flag_metaslot_auto_key_migrate;
4423089Swyllys 		(void) memcpy(puent2->metaslot_ks_slot,
4433089Swyllys 		    puent1->metaslot_ks_slot, SLOT_DESCRIPTION_SIZE);
4443089Swyllys 		(void) memcpy(puent2->metaslot_ks_token,
4453089Swyllys 		    puent1->metaslot_ks_token, TOKEN_LABEL_SIZE);
4463089Swyllys 		puent2->count = puent1->count;
4473089Swyllys 		return (puent2);
4483089Swyllys 	}
4493089Swyllys }
4503089Swyllys 
4513089Swyllys /*
4523089Swyllys  * Find the entry in the "pkcs11.conf" file with "libname" as the provider
4533089Swyllys  * name. Return the entry if found, otherwise return NULL.
4543089Swyllys  */
4553089Swyllys uentry_t *
4563089Swyllys getent_uef(char *libname)
4573089Swyllys {
4583089Swyllys 	uentrylist_t	*pliblist = NULL;
4593089Swyllys 	uentrylist_t	*plib = NULL;
4603089Swyllys 	uentry_t	*puent = NULL;
4613089Swyllys 	boolean_t	found = B_FALSE;
4623089Swyllys 
4633089Swyllys 	if (libname == NULL) {
4643089Swyllys 		return (NULL);
4653089Swyllys 	}
4663089Swyllys 
4673089Swyllys 	if ((get_pkcs11conf_info(&pliblist)) == FAILURE) {
4683089Swyllys 		return (NULL);
4693089Swyllys 	}
4703089Swyllys 
4713089Swyllys 	plib = pliblist;
4723089Swyllys 	while (plib) {
4733089Swyllys 		if (strcmp(plib->puent->name, libname) == 0) {
4743089Swyllys 			found = B_TRUE;
4753089Swyllys 			break;
4763089Swyllys 		} else {
4773089Swyllys 			plib = plib->next;
4783089Swyllys 		}
4793089Swyllys 	}
4803089Swyllys 
4813089Swyllys 	if (found) {
4823089Swyllys 		puent = dup_uentry(plib->puent);
4833089Swyllys 	}
4843089Swyllys 
4853089Swyllys 	free_uentrylist(pliblist);
4863089Swyllys 	return (puent);
4873089Swyllys }
4883089Swyllys 
4893089Swyllys 
4903089Swyllys 
4913089Swyllys /*
4923089Swyllys  * Retrieve the metaslot information from the pkcs11.conf file.
4933089Swyllys  * This function returns SUCCESS if successfully done; otherwise it returns
4943089Swyllys  * FAILURE.   If successful, the caller is responsible to free the space
4953089Swyllys  * allocated for objectstore_slot_info and objectstore_token_info.
4963089Swyllys  */
4973089Swyllys int
4983089Swyllys get_metaslot_info(boolean_t  *status_enabled, boolean_t *migrate_enabled,
4993089Swyllys     char **objectstore_slot_info, char **objectstore_token_info)
5003089Swyllys {
5013089Swyllys 
5023089Swyllys 	int rc = SUCCESS;
5033089Swyllys 	uentry_t *puent;
5043089Swyllys 	char *buf1 = NULL;
5053089Swyllys 	char *buf2 = NULL;
5063089Swyllys 
5073089Swyllys 	if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
5083089Swyllys 		/* metaslot entry doesn't exist */
5093089Swyllys 		return (FAILURE);
5103089Swyllys 	}
5113089Swyllys 
5123089Swyllys 	*status_enabled = puent->flag_metaslot_enabled;
5133089Swyllys 	*migrate_enabled = puent->flag_metaslot_auto_key_migrate;
5143089Swyllys 
5153089Swyllys 	buf1 = malloc(SLOT_DESCRIPTION_SIZE);
5163089Swyllys 	if (buf1 == NULL) {
5173089Swyllys 		cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n");
5183089Swyllys 		rc = FAILURE;
5193089Swyllys 		goto out;
5203089Swyllys 	}
5213089Swyllys 	(void) strcpy(buf1, (const char *) puent->metaslot_ks_slot);
5223089Swyllys 	*objectstore_slot_info = buf1;
5233089Swyllys 
5243089Swyllys 	buf2 = malloc(TOKEN_LABEL_SIZE);
5253089Swyllys 	if (objectstore_slot_info == NULL) {
5263089Swyllys 		cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n");
5273089Swyllys 		rc = FAILURE;
5283089Swyllys 		goto out;
5293089Swyllys 	}
5303089Swyllys 	(void) strcpy(buf2, (const char *) puent->metaslot_ks_token);
5313089Swyllys 	*objectstore_token_info = buf2;
5323089Swyllys 
5333089Swyllys out:
5343089Swyllys 	if (puent != NULL) {
5353089Swyllys 		free_uentry(puent);
5363089Swyllys 	}
5373089Swyllys 
5383089Swyllys 	if (rc == FAILURE) {
5393089Swyllys 		if (buf1 != NULL) {
5403089Swyllys 			free(buf1);
5413089Swyllys 		}
5423089Swyllys 		if (buf2 != NULL) {
5433089Swyllys 			free(buf2);
5443089Swyllys 		}
5453089Swyllys 	}
5463089Swyllys 
5473089Swyllys 	return (rc);
5483089Swyllys }
549*10500SHai-May.Chao@Sun.COM 
550*10500SHai-May.Chao@Sun.COM static CK_RV
551*10500SHai-May.Chao@Sun.COM parse_fips_mode(char *buf, int *mode)
552*10500SHai-May.Chao@Sun.COM {
553*10500SHai-May.Chao@Sun.COM 
554*10500SHai-May.Chao@Sun.COM 	char *value;
555*10500SHai-May.Chao@Sun.COM 
556*10500SHai-May.Chao@Sun.COM 	if (strncmp(buf, EF_FIPS_STATUS, sizeof (EF_FIPS_STATUS) - 1) == 0) {
557*10500SHai-May.Chao@Sun.COM 		if (value = strpbrk(buf, SEP_EQUAL)) {
558*10500SHai-May.Chao@Sun.COM 			value++; /* get rid of = */
559*10500SHai-May.Chao@Sun.COM 			if (strcmp(value, DISABLED_KEYWORD) == 0) {
560*10500SHai-May.Chao@Sun.COM 				*mode = CRYPTO_FIPS_MODE_DISABLED;
561*10500SHai-May.Chao@Sun.COM 			} else if (strcmp(value, ENABLED_KEYWORD) == 0) {
562*10500SHai-May.Chao@Sun.COM 				*mode = CRYPTO_FIPS_MODE_ENABLED;
563*10500SHai-May.Chao@Sun.COM 			} else {
564*10500SHai-May.Chao@Sun.COM 				cryptoerror(LOG_ERR,
565*10500SHai-May.Chao@Sun.COM 				    "failed to parse kcf.conf file.\n");
566*10500SHai-May.Chao@Sun.COM 				return (CKR_FUNCTION_FAILED);
567*10500SHai-May.Chao@Sun.COM 			}
568*10500SHai-May.Chao@Sun.COM 			return (CKR_OK);
569*10500SHai-May.Chao@Sun.COM 		} else {
570*10500SHai-May.Chao@Sun.COM 			return (CKR_FUNCTION_FAILED);
571*10500SHai-May.Chao@Sun.COM 		}
572*10500SHai-May.Chao@Sun.COM 	} else {
573*10500SHai-May.Chao@Sun.COM 		/* should not come here */
574*10500SHai-May.Chao@Sun.COM 		return (CKR_FUNCTION_FAILED);
575*10500SHai-May.Chao@Sun.COM 	}
576*10500SHai-May.Chao@Sun.COM 
577*10500SHai-May.Chao@Sun.COM }
578*10500SHai-May.Chao@Sun.COM 
579*10500SHai-May.Chao@Sun.COM static boolean_t
580*10500SHai-May.Chao@Sun.COM is_fips(char *name)
581*10500SHai-May.Chao@Sun.COM {
582*10500SHai-May.Chao@Sun.COM 	if (strcmp(name, FIPS_KEYWORD) == 0) {
583*10500SHai-May.Chao@Sun.COM 		return (B_TRUE);
584*10500SHai-May.Chao@Sun.COM 	} else {
585*10500SHai-May.Chao@Sun.COM 		return (B_FALSE);
586*10500SHai-May.Chao@Sun.COM 	}
587*10500SHai-May.Chao@Sun.COM }
588*10500SHai-May.Chao@Sun.COM 
589*10500SHai-May.Chao@Sun.COM CK_RV
590*10500SHai-May.Chao@Sun.COM get_fips_mode(int *mode)
591*10500SHai-May.Chao@Sun.COM {
592*10500SHai-May.Chao@Sun.COM 	FILE	*pfile = NULL;
593*10500SHai-May.Chao@Sun.COM 	char	buffer[BUFSIZ];
594*10500SHai-May.Chao@Sun.COM 	int	len;
595*10500SHai-May.Chao@Sun.COM 	CK_RV	rc = CKR_OK;
596*10500SHai-May.Chao@Sun.COM 	int found = 0;
597*10500SHai-May.Chao@Sun.COM 	char *token1;
598*10500SHai-May.Chao@Sun.COM 
599*10500SHai-May.Chao@Sun.COM 	if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) {
600*10500SHai-May.Chao@Sun.COM 		cryptoerror(LOG_ERR,
601*10500SHai-May.Chao@Sun.COM 		    "failed to open the kcf.conf file for read only.");
602*10500SHai-May.Chao@Sun.COM 		return (CKR_FUNCTION_FAILED);
603*10500SHai-May.Chao@Sun.COM 	}
604*10500SHai-May.Chao@Sun.COM 
605*10500SHai-May.Chao@Sun.COM 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
606*10500SHai-May.Chao@Sun.COM 		if (buffer[0] == '#' || buffer[0] == ' ' ||
607*10500SHai-May.Chao@Sun.COM 		    buffer[0] == '\n'|| buffer[0] == '\t') {
608*10500SHai-May.Chao@Sun.COM 			continue;   /* ignore comment lines */
609*10500SHai-May.Chao@Sun.COM 		}
610*10500SHai-May.Chao@Sun.COM 
611*10500SHai-May.Chao@Sun.COM 		len = strlen(buffer);
612*10500SHai-May.Chao@Sun.COM 		if (buffer[len - 1] == '\n') { /* get rid of trailing '\n' */
613*10500SHai-May.Chao@Sun.COM 			len--;
614*10500SHai-May.Chao@Sun.COM 		}
615*10500SHai-May.Chao@Sun.COM 		buffer[len] = '\0';
616*10500SHai-May.Chao@Sun.COM 
617*10500SHai-May.Chao@Sun.COM 		/* Get provider name */
618*10500SHai-May.Chao@Sun.COM 		if ((token1 = strtok(buffer, SEP_COLON)) ==
619*10500SHai-May.Chao@Sun.COM 		    NULL) { /* buf is NULL */
620*10500SHai-May.Chao@Sun.COM 			return (CKR_FUNCTION_FAILED);
621*10500SHai-May.Chao@Sun.COM 		};
622*10500SHai-May.Chao@Sun.COM 
623*10500SHai-May.Chao@Sun.COM 		if (is_fips(token1)) {
624*10500SHai-May.Chao@Sun.COM 			if ((rc = parse_fips_mode(buffer + strlen(token1) + 1,
625*10500SHai-May.Chao@Sun.COM 			    mode)) != CKR_OK) {
626*10500SHai-May.Chao@Sun.COM 				goto out;
627*10500SHai-May.Chao@Sun.COM 			} else {
628*10500SHai-May.Chao@Sun.COM 				found++;
629*10500SHai-May.Chao@Sun.COM 				break;
630*10500SHai-May.Chao@Sun.COM 			}
631*10500SHai-May.Chao@Sun.COM 		} else {
632*10500SHai-May.Chao@Sun.COM 			continue;
633*10500SHai-May.Chao@Sun.COM 		}
634*10500SHai-May.Chao@Sun.COM 	}
635*10500SHai-May.Chao@Sun.COM 
636*10500SHai-May.Chao@Sun.COM 	if (!found) {
637*10500SHai-May.Chao@Sun.COM 		*mode = CRYPTO_FIPS_MODE_DISABLED;
638*10500SHai-May.Chao@Sun.COM 	}
639*10500SHai-May.Chao@Sun.COM 
640*10500SHai-May.Chao@Sun.COM out:
641*10500SHai-May.Chao@Sun.COM 	(void) fclose(pfile);
642*10500SHai-May.Chao@Sun.COM 	return (rc);
643*10500SHai-May.Chao@Sun.COM }
644