xref: /illumos-gate/usr/src/lib/libcryptoutil/common/config_parsing.c (revision b5a2d8455dfa3190fc977c4bec53e91c99012767)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*b5a2d845SHai-May Chao  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <errno.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <locale.h>
317c478bd9Sstevel@tonic-gate #include <stdlib.h>
327c478bd9Sstevel@tonic-gate #include "cryptoutil.h"
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate static int uef_interpret(char *, uentry_t **);
357c478bd9Sstevel@tonic-gate static int parse_policylist(char *, uentry_t *);
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate  * Retrieve the user-level provider info from the pkcs11.conf file.
397c478bd9Sstevel@tonic-gate  * If successful, the result is returned from the ppliblist argument.
407c478bd9Sstevel@tonic-gate  * This function returns SUCCESS if successfully done; otherwise it returns
417c478bd9Sstevel@tonic-gate  * FAILURE.
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate int
447c478bd9Sstevel@tonic-gate get_pkcs11conf_info(uentrylist_t **ppliblist)
457c478bd9Sstevel@tonic-gate {
467c478bd9Sstevel@tonic-gate 	FILE *pfile;
477c478bd9Sstevel@tonic-gate 	char buffer[BUFSIZ];
487c478bd9Sstevel@tonic-gate 	size_t len;
497c478bd9Sstevel@tonic-gate 	uentry_t *pent;
507c478bd9Sstevel@tonic-gate 	uentrylist_t *pentlist;
517c478bd9Sstevel@tonic-gate 	uentrylist_t *pcur;
527c478bd9Sstevel@tonic-gate 	int rc = SUCCESS;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	*ppliblist = NULL;
55004388ebScasper 	if ((pfile = fopen(_PATH_PKCS11_CONF, "rF")) == NULL) {
567c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_PKCS11_CONF);
577c478bd9Sstevel@tonic-gate 		return (FAILURE);
587c478bd9Sstevel@tonic-gate 	}
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
617c478bd9Sstevel@tonic-gate 		if (buffer[0] == '#' || buffer[0] == ' ' ||
627c478bd9Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t') {
637c478bd9Sstevel@tonic-gate 			continue;   /* ignore comment lines */
647c478bd9Sstevel@tonic-gate 		}
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 		len = strlen(buffer);
677c478bd9Sstevel@tonic-gate 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
687c478bd9Sstevel@tonic-gate 			len--;
697c478bd9Sstevel@tonic-gate 		}
707c478bd9Sstevel@tonic-gate 		buffer[len] = '\0';
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 		if ((rc = uef_interpret(buffer,  &pent)) != SUCCESS) {
737c478bd9Sstevel@tonic-gate 			break;
747c478bd9Sstevel@tonic-gate 		}
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 		/* append pent into ppliblist */
777c478bd9Sstevel@tonic-gate 		pentlist = malloc(sizeof (uentrylist_t));
787c478bd9Sstevel@tonic-gate 		if (pentlist == NULL) {
797c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
807c478bd9Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
817c478bd9Sstevel@tonic-gate 			free_uentry(pent);
827c478bd9Sstevel@tonic-gate 			rc = FAILURE;
837c478bd9Sstevel@tonic-gate 			break;
847c478bd9Sstevel@tonic-gate 		}
857c478bd9Sstevel@tonic-gate 		pentlist->puent = pent;
867c478bd9Sstevel@tonic-gate 		pentlist->next = NULL;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 		if (*ppliblist == NULL) {
897c478bd9Sstevel@tonic-gate 			*ppliblist = pcur = pentlist;
907c478bd9Sstevel@tonic-gate 		} else {
917c478bd9Sstevel@tonic-gate 			pcur->next = pentlist;
927c478bd9Sstevel@tonic-gate 			pcur = pcur->next;
937c478bd9Sstevel@tonic-gate 		}
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	(void) fclose(pfile);
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	if (rc != SUCCESS) {
997c478bd9Sstevel@tonic-gate 		free_uentrylist(*ppliblist);
1007c478bd9Sstevel@tonic-gate 		*ppliblist = NULL;
1017c478bd9Sstevel@tonic-gate 	}
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	return (rc);
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * This routine converts a char string into a uentry_t structure
1097c478bd9Sstevel@tonic-gate  * The input string "buf" should be one of the following:
1107c478bd9Sstevel@tonic-gate  *	library_name
1117c478bd9Sstevel@tonic-gate  *	library_name:NO_RANDOM
1127c478bd9Sstevel@tonic-gate  *	library_name:disabledlist=m1,m2,...,mk
1137c478bd9Sstevel@tonic-gate  *	library_name:disabledlist=m1,m2,...,mk;NO_RANDOM
1147c478bd9Sstevel@tonic-gate  *	library_name:enabledlist=
1157c478bd9Sstevel@tonic-gate  *	library_name:enabledlist=;NO_RANDOM
1167c478bd9Sstevel@tonic-gate  *	library_name:enabledlist=m1,m2,...,mk
1177c478bd9Sstevel@tonic-gate  *	library_name:enabledlist=m1,m2,...,mk;NO_RANDOM
1187c478bd9Sstevel@tonic-gate  *	metaslot:status=enabled;enabledlist=m1,m2,....;slot=<slot-description>;\
1197c478bd9Sstevel@tonic-gate  *	token=<token-label>
1207c478bd9Sstevel@tonic-gate  *
1217c478bd9Sstevel@tonic-gate  * Note:
1227c478bd9Sstevel@tonic-gate  *	The mechanisms m1,..mk are in hex form. For example, "0x00000210"
1237c478bd9Sstevel@tonic-gate  *	for CKM_MD5.
1247c478bd9Sstevel@tonic-gate  *
1257c478bd9Sstevel@tonic-gate  *	For the metaslot entry, "enabledlist", "slot", "auto_key_migrate"
1267c478bd9Sstevel@tonic-gate  * 	or "token" is optional
1277c478bd9Sstevel@tonic-gate  */
1287c478bd9Sstevel@tonic-gate static int
1297c478bd9Sstevel@tonic-gate uef_interpret(char *buf, uentry_t **ppent)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	uentry_t *pent;
1327c478bd9Sstevel@tonic-gate 	char	*token1;
1337c478bd9Sstevel@tonic-gate 	char	*token2;
1347c478bd9Sstevel@tonic-gate 	char	*lasts;
1357c478bd9Sstevel@tonic-gate 	int	rc;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	*ppent = NULL;
1387c478bd9Sstevel@tonic-gate 	if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) {
1397c478bd9Sstevel@tonic-gate 		/* buf is NULL */
1407c478bd9Sstevel@tonic-gate 		return (FAILURE);
1417c478bd9Sstevel@tonic-gate 	};
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	pent = calloc(sizeof (uentry_t), 1);
1447c478bd9Sstevel@tonic-gate 	if (pent == NULL) {
1457c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
1467c478bd9Sstevel@tonic-gate 		    _PATH_PKCS11_CONF);
1477c478bd9Sstevel@tonic-gate 		return (FAILURE);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 	(void) strlcpy(pent->name, token1, sizeof (pent->name));
1507c478bd9Sstevel@tonic-gate 	/*
1517c478bd9Sstevel@tonic-gate 	 * in case metaslot_auto_key_migrate is not specified, it should
1527c478bd9Sstevel@tonic-gate 	 * be default to true
1537c478bd9Sstevel@tonic-gate 	 */
1547c478bd9Sstevel@tonic-gate 	pent->flag_metaslot_auto_key_migrate = B_TRUE;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	while ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) != NULL) {
1577c478bd9Sstevel@tonic-gate 		if ((rc = parse_policylist(token2, pent)) != SUCCESS) {
1587c478bd9Sstevel@tonic-gate 			free_uentry(pent);
1597c478bd9Sstevel@tonic-gate 			return (rc);
1607c478bd9Sstevel@tonic-gate 		}
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	*ppent = pent;
1647c478bd9Sstevel@tonic-gate 	return (SUCCESS);
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate  * This routine parses the policy list and stored the result in the argument
1707c478bd9Sstevel@tonic-gate  * pent.
1717c478bd9Sstevel@tonic-gate  *
1727c478bd9Sstevel@tonic-gate  * 	Arg buf: input only, its format should be one of the following:
1737c478bd9Sstevel@tonic-gate  *     		enabledlist=
1747c478bd9Sstevel@tonic-gate  *		enabledlist=m1,m2,...,mk
1757c478bd9Sstevel@tonic-gate  *		disabledlist=m1,m2,...,mk
1767c478bd9Sstevel@tonic-gate  *		NO_RANDOM
1777c478bd9Sstevel@tonic-gate  *		metaslot_status=enabled|disabled
1787c478bd9Sstevel@tonic-gate  *		metaslot_token=<token-label>
1797c478bd9Sstevel@tonic-gate  *		metaslot_slot=<slot-description.
1807c478bd9Sstevel@tonic-gate  *
1817c478bd9Sstevel@tonic-gate  *	Arg pent: input/output
1827c478bd9Sstevel@tonic-gate  *
1837c478bd9Sstevel@tonic-gate  *      return: SUCCESS or FAILURE
1847c478bd9Sstevel@tonic-gate  */
1857c478bd9Sstevel@tonic-gate static int
1867c478bd9Sstevel@tonic-gate parse_policylist(char *buf, uentry_t *pent)
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate 	umechlist_t *phead = NULL;
1897c478bd9Sstevel@tonic-gate 	umechlist_t *pcur = NULL;
1907c478bd9Sstevel@tonic-gate 	umechlist_t *pmech;
1917c478bd9Sstevel@tonic-gate 	char *next_token;
1927c478bd9Sstevel@tonic-gate 	char *value;
1937c478bd9Sstevel@tonic-gate 	char *lasts;
1947c478bd9Sstevel@tonic-gate 	int count = 0;
1957c478bd9Sstevel@tonic-gate 	int rc = SUCCESS;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if (pent == NULL) {
1987c478bd9Sstevel@tonic-gate 		return (FAILURE);
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	if (strncmp(buf, EF_DISABLED, sizeof (EF_DISABLED) - 1) == 0) {
2027c478bd9Sstevel@tonic-gate 		pent->flag_enabledlist = B_FALSE;
2037c478bd9Sstevel@tonic-gate 	} else if (strncmp(buf, EF_ENABLED, sizeof (EF_ENABLED) - 1) == 0) {
2047c478bd9Sstevel@tonic-gate 		pent->flag_enabledlist = B_TRUE;
2057c478bd9Sstevel@tonic-gate 	} else if (strncmp(buf, EF_NORANDOM, sizeof (EF_NORANDOM) - 1) == 0) {
2067c478bd9Sstevel@tonic-gate 		pent->flag_norandom = B_TRUE;
2077c478bd9Sstevel@tonic-gate 		return (rc);
2087c478bd9Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_TOKEN,
2097c478bd9Sstevel@tonic-gate 	    sizeof (METASLOT_TOKEN) - 1) == 0) {
2107c478bd9Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2117c478bd9Sstevel@tonic-gate 			value++; /* get rid of = */
2127c478bd9Sstevel@tonic-gate 			(void) strlcpy((char *)pent->metaslot_ks_token, value,
21399ebb4caSwyllys 			    sizeof (pent->metaslot_ks_token));
2147c478bd9Sstevel@tonic-gate 			return (SUCCESS);
2157c478bd9Sstevel@tonic-gate 		} else {
2167c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2177c478bd9Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2187c478bd9Sstevel@tonic-gate 			return (FAILURE);
2197c478bd9Sstevel@tonic-gate 		}
2207c478bd9Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_SLOT,
2217c478bd9Sstevel@tonic-gate 	    sizeof (METASLOT_SLOT) - 1) == 0) {
2227c478bd9Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2237c478bd9Sstevel@tonic-gate 			value++; /* get rid of = */
2247c478bd9Sstevel@tonic-gate 			(void) strlcpy((char *)pent->metaslot_ks_slot, value,
22599ebb4caSwyllys 			    sizeof (pent->metaslot_ks_slot));
2267c478bd9Sstevel@tonic-gate 			return (SUCCESS);
2277c478bd9Sstevel@tonic-gate 		} else {
2287c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2297c478bd9Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2307c478bd9Sstevel@tonic-gate 			return (FAILURE);
2317c478bd9Sstevel@tonic-gate 		}
2327c478bd9Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_STATUS,
2337c478bd9Sstevel@tonic-gate 	    sizeof (METASLOT_STATUS) - 1) == 0) {
2347c478bd9Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2357c478bd9Sstevel@tonic-gate 			value++; /* get rid of = */
236*b5a2d845SHai-May Chao 			if (strcmp(value, DISABLED_KEYWORD) == 0) {
2377c478bd9Sstevel@tonic-gate 				pent->flag_metaslot_enabled = B_FALSE;
238*b5a2d845SHai-May Chao 			} else if (strcmp(value, ENABLED_KEYWORD) == 0) {
2397c478bd9Sstevel@tonic-gate 				pent->flag_metaslot_enabled = B_TRUE;
2407c478bd9Sstevel@tonic-gate 			} else {
2417c478bd9Sstevel@tonic-gate 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
2427c478bd9Sstevel@tonic-gate 				    _PATH_PKCS11_CONF);
2437c478bd9Sstevel@tonic-gate 				return (FAILURE);
2447c478bd9Sstevel@tonic-gate 			}
2457c478bd9Sstevel@tonic-gate 			return (SUCCESS);
2467c478bd9Sstevel@tonic-gate 		} else {
2477c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2487c478bd9Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2497c478bd9Sstevel@tonic-gate 			return (FAILURE);
2507c478bd9Sstevel@tonic-gate 		}
2517c478bd9Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_AUTO_KEY_MIGRATE,
2527c478bd9Sstevel@tonic-gate 	    sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) {
2537c478bd9Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2547c478bd9Sstevel@tonic-gate 			value++; /* get rid of = */
255*b5a2d845SHai-May Chao 			if (strcmp(value, DISABLED_KEYWORD) == 0) {
2567c478bd9Sstevel@tonic-gate 				pent->flag_metaslot_auto_key_migrate = B_FALSE;
257*b5a2d845SHai-May Chao 			} else if (strcmp(value, ENABLED_KEYWORD) == 0) {
2587c478bd9Sstevel@tonic-gate 				pent->flag_metaslot_auto_key_migrate = B_TRUE;
2597c478bd9Sstevel@tonic-gate 			} else {
2607c478bd9Sstevel@tonic-gate 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
2617c478bd9Sstevel@tonic-gate 				    _PATH_PKCS11_CONF);
2627c478bd9Sstevel@tonic-gate 				return (FAILURE);
2637c478bd9Sstevel@tonic-gate 			}
2647c478bd9Sstevel@tonic-gate 			return (SUCCESS);
2657c478bd9Sstevel@tonic-gate 		} else {
2667c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2677c478bd9Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2687c478bd9Sstevel@tonic-gate 			return (FAILURE);
2697c478bd9Sstevel@tonic-gate 		}
2707c478bd9Sstevel@tonic-gate 	} else {
2717c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to parse %s.\n",
2727c478bd9Sstevel@tonic-gate 		    _PATH_PKCS11_CONF);
2737c478bd9Sstevel@tonic-gate 		return (FAILURE);
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	if (value = strpbrk(buf, SEP_EQUAL)) {
2777c478bd9Sstevel@tonic-gate 		value++; /* get rid of = */
2787c478bd9Sstevel@tonic-gate 	}
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	if ((next_token = strtok_r(value, SEP_COMMA, &lasts)) == NULL) {
2817c478bd9Sstevel@tonic-gate 		if (pent->flag_enabledlist) {
2827c478bd9Sstevel@tonic-gate 			return (SUCCESS);
2837c478bd9Sstevel@tonic-gate 		} else {
2847c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2857c478bd9Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2867c478bd9Sstevel@tonic-gate 			return (FAILURE);
2877c478bd9Sstevel@tonic-gate 		}
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	while (next_token) {
2917c478bd9Sstevel@tonic-gate 		if ((pmech = create_umech(next_token)) == NULL) {
2927c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
2937c478bd9Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2947c478bd9Sstevel@tonic-gate 			rc = FAILURE;
2957c478bd9Sstevel@tonic-gate 			break;
2967c478bd9Sstevel@tonic-gate 		}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 		if (phead == NULL) {
2997c478bd9Sstevel@tonic-gate 			phead = pcur = pmech;
3007c478bd9Sstevel@tonic-gate 		} else {
3017c478bd9Sstevel@tonic-gate 			pcur->next = pmech;
3027c478bd9Sstevel@tonic-gate 			pcur = pcur->next;
3037c478bd9Sstevel@tonic-gate 		}
3047c478bd9Sstevel@tonic-gate 		count++;
3057c478bd9Sstevel@tonic-gate 		next_token = strtok_r(NULL, SEP_COMMA, &lasts);
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	if (rc == SUCCESS) {
3097c478bd9Sstevel@tonic-gate 		pent->policylist = phead;
3107c478bd9Sstevel@tonic-gate 		pent->count = count;
3117c478bd9Sstevel@tonic-gate 	} else {
3127c478bd9Sstevel@tonic-gate 		free_umechlist(phead);
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	return (rc);
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate  * Create one item of type umechlist_t with the mechanism name.  A NULL is
3217c478bd9Sstevel@tonic-gate  * returned when the input name is NULL or the heap memory is insufficient.
3227c478bd9Sstevel@tonic-gate  */
3237c478bd9Sstevel@tonic-gate umechlist_t *
3247c478bd9Sstevel@tonic-gate create_umech(char *name)
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate 	umechlist_t *pmech = NULL;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	if (name == NULL) {
3297c478bd9Sstevel@tonic-gate 		return (NULL);
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	if ((pmech = malloc(sizeof (umechlist_t))) != NULL) {
3337c478bd9Sstevel@tonic-gate 		(void) strlcpy(pmech->name, name, sizeof (pmech->name));
3347c478bd9Sstevel@tonic-gate 		pmech->next = NULL;
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	return (pmech);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate void
3427c478bd9Sstevel@tonic-gate free_umechlist(umechlist_t *plist)
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate 	umechlist_t *pnext;
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	while (plist != NULL) {
3477c478bd9Sstevel@tonic-gate 		pnext = plist->next;
3487c478bd9Sstevel@tonic-gate 		free(plist);
3497c478bd9Sstevel@tonic-gate 		plist = pnext;
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate void
3557c478bd9Sstevel@tonic-gate free_uentry(uentry_t  *pent)
3567c478bd9Sstevel@tonic-gate {
3577c478bd9Sstevel@tonic-gate 	if (pent == NULL) {
3587c478bd9Sstevel@tonic-gate 		return;
3597c478bd9Sstevel@tonic-gate 	} else {
3607c478bd9Sstevel@tonic-gate 		free_umechlist(pent->policylist);
3617c478bd9Sstevel@tonic-gate 		free(pent);
3627c478bd9Sstevel@tonic-gate 	}
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate void
3677c478bd9Sstevel@tonic-gate free_uentrylist(uentrylist_t *entrylist)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate 	uentrylist_t *pnext;
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	while (entrylist != NULL) {
3727c478bd9Sstevel@tonic-gate 		pnext = entrylist->next;
3737c478bd9Sstevel@tonic-gate 		free_uentry(entrylist->puent);
3747c478bd9Sstevel@tonic-gate 		free(entrylist);
3757c478bd9Sstevel@tonic-gate 		entrylist = pnext;
3767c478bd9Sstevel@tonic-gate 	}
3777c478bd9Sstevel@tonic-gate }
37899ebb4caSwyllys 
37999ebb4caSwyllys 
38099ebb4caSwyllys 
38199ebb4caSwyllys /*
38299ebb4caSwyllys  * Duplicate an UEF mechanism list.  A NULL pointer is returned if out of
38399ebb4caSwyllys  * memory or the input argument is NULL.
38499ebb4caSwyllys  */
38599ebb4caSwyllys static umechlist_t *
38699ebb4caSwyllys dup_umechlist(umechlist_t *plist)
38799ebb4caSwyllys {
38899ebb4caSwyllys 	umechlist_t *pres = NULL;
38999ebb4caSwyllys 	umechlist_t *pcur;
39099ebb4caSwyllys 	umechlist_t *ptmp;
39199ebb4caSwyllys 	int rc = SUCCESS;
39299ebb4caSwyllys 
39399ebb4caSwyllys 	while (plist != NULL) {
39499ebb4caSwyllys 		if (!(ptmp = create_umech(plist->name))) {
39599ebb4caSwyllys 			rc = FAILURE;
39699ebb4caSwyllys 			break;
39799ebb4caSwyllys 		}
39899ebb4caSwyllys 
39999ebb4caSwyllys 		if (pres == NULL) {
40099ebb4caSwyllys 			pres = pcur = ptmp;
40199ebb4caSwyllys 		} else {
40299ebb4caSwyllys 			pcur->next = ptmp;
40399ebb4caSwyllys 			pcur = pcur->next;
40499ebb4caSwyllys 		}
40599ebb4caSwyllys 		plist = plist->next;
40699ebb4caSwyllys 	}
40799ebb4caSwyllys 
40899ebb4caSwyllys 	if (rc != SUCCESS) {
40999ebb4caSwyllys 		free_umechlist(pres);
41099ebb4caSwyllys 		return (NULL);
41199ebb4caSwyllys 	}
41299ebb4caSwyllys 
41399ebb4caSwyllys 	return (pres);
41499ebb4caSwyllys }
41599ebb4caSwyllys 
41699ebb4caSwyllys 
41799ebb4caSwyllys /*
41899ebb4caSwyllys  * Duplicate an uentry.  A NULL pointer is returned if out of memory
41999ebb4caSwyllys  * or the input argument is NULL.
42099ebb4caSwyllys  */
42199ebb4caSwyllys static uentry_t *
42299ebb4caSwyllys dup_uentry(uentry_t *puent1)
42399ebb4caSwyllys {
42499ebb4caSwyllys 	uentry_t *puent2 = NULL;
42599ebb4caSwyllys 
42699ebb4caSwyllys 	if (puent1 == NULL) {
42799ebb4caSwyllys 		return (NULL);
42899ebb4caSwyllys 	}
42999ebb4caSwyllys 
43099ebb4caSwyllys 	if ((puent2 = malloc(sizeof (uentry_t))) == NULL) {
43199ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("out of memory."));
43299ebb4caSwyllys 		return (NULL);
43399ebb4caSwyllys 	} else {
43499ebb4caSwyllys 		(void) strlcpy(puent2->name, puent1->name,
43599ebb4caSwyllys 		    sizeof (puent2->name));
43699ebb4caSwyllys 		puent2->flag_norandom = puent1->flag_norandom;
43799ebb4caSwyllys 		puent2->flag_enabledlist = puent1->flag_enabledlist;
43899ebb4caSwyllys 		puent2->policylist = dup_umechlist(puent1->policylist);
43999ebb4caSwyllys 		puent2->flag_metaslot_enabled = puent1->flag_metaslot_enabled;
44099ebb4caSwyllys 		puent2->flag_metaslot_auto_key_migrate
44199ebb4caSwyllys 		    = puent1->flag_metaslot_auto_key_migrate;
44299ebb4caSwyllys 		(void) memcpy(puent2->metaslot_ks_slot,
44399ebb4caSwyllys 		    puent1->metaslot_ks_slot, SLOT_DESCRIPTION_SIZE);
44499ebb4caSwyllys 		(void) memcpy(puent2->metaslot_ks_token,
44599ebb4caSwyllys 		    puent1->metaslot_ks_token, TOKEN_LABEL_SIZE);
44699ebb4caSwyllys 		puent2->count = puent1->count;
44799ebb4caSwyllys 		return (puent2);
44899ebb4caSwyllys 	}
44999ebb4caSwyllys }
45099ebb4caSwyllys 
45199ebb4caSwyllys /*
45299ebb4caSwyllys  * Find the entry in the "pkcs11.conf" file with "libname" as the provider
45399ebb4caSwyllys  * name. Return the entry if found, otherwise return NULL.
45499ebb4caSwyllys  */
45599ebb4caSwyllys uentry_t *
45699ebb4caSwyllys getent_uef(char *libname)
45799ebb4caSwyllys {
45899ebb4caSwyllys 	uentrylist_t	*pliblist = NULL;
45999ebb4caSwyllys 	uentrylist_t	*plib = NULL;
46099ebb4caSwyllys 	uentry_t	*puent = NULL;
46199ebb4caSwyllys 	boolean_t	found = B_FALSE;
46299ebb4caSwyllys 
46399ebb4caSwyllys 	if (libname == NULL) {
46499ebb4caSwyllys 		return (NULL);
46599ebb4caSwyllys 	}
46699ebb4caSwyllys 
46799ebb4caSwyllys 	if ((get_pkcs11conf_info(&pliblist)) == FAILURE) {
46899ebb4caSwyllys 		return (NULL);
46999ebb4caSwyllys 	}
47099ebb4caSwyllys 
47199ebb4caSwyllys 	plib = pliblist;
47299ebb4caSwyllys 	while (plib) {
47399ebb4caSwyllys 		if (strcmp(plib->puent->name, libname) == 0) {
47499ebb4caSwyllys 			found = B_TRUE;
47599ebb4caSwyllys 			break;
47699ebb4caSwyllys 		} else {
47799ebb4caSwyllys 			plib = plib->next;
47899ebb4caSwyllys 		}
47999ebb4caSwyllys 	}
48099ebb4caSwyllys 
48199ebb4caSwyllys 	if (found) {
48299ebb4caSwyllys 		puent = dup_uentry(plib->puent);
48399ebb4caSwyllys 	}
48499ebb4caSwyllys 
48599ebb4caSwyllys 	free_uentrylist(pliblist);
48699ebb4caSwyllys 	return (puent);
48799ebb4caSwyllys }
48899ebb4caSwyllys 
48999ebb4caSwyllys 
49099ebb4caSwyllys 
49199ebb4caSwyllys /*
49299ebb4caSwyllys  * Retrieve the metaslot information from the pkcs11.conf file.
49399ebb4caSwyllys  * This function returns SUCCESS if successfully done; otherwise it returns
49499ebb4caSwyllys  * FAILURE.   If successful, the caller is responsible to free the space
49599ebb4caSwyllys  * allocated for objectstore_slot_info and objectstore_token_info.
49699ebb4caSwyllys  */
49799ebb4caSwyllys int
49899ebb4caSwyllys get_metaslot_info(boolean_t  *status_enabled, boolean_t *migrate_enabled,
49999ebb4caSwyllys     char **objectstore_slot_info, char **objectstore_token_info)
50099ebb4caSwyllys {
50199ebb4caSwyllys 
50299ebb4caSwyllys 	int rc = SUCCESS;
50399ebb4caSwyllys 	uentry_t *puent;
50499ebb4caSwyllys 	char *buf1 = NULL;
50599ebb4caSwyllys 	char *buf2 = NULL;
50699ebb4caSwyllys 
50799ebb4caSwyllys 	if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
50899ebb4caSwyllys 		/* metaslot entry doesn't exist */
50999ebb4caSwyllys 		return (FAILURE);
51099ebb4caSwyllys 	}
51199ebb4caSwyllys 
51299ebb4caSwyllys 	*status_enabled = puent->flag_metaslot_enabled;
51399ebb4caSwyllys 	*migrate_enabled = puent->flag_metaslot_auto_key_migrate;
51499ebb4caSwyllys 
51599ebb4caSwyllys 	buf1 = malloc(SLOT_DESCRIPTION_SIZE);
51699ebb4caSwyllys 	if (buf1 == NULL) {
51799ebb4caSwyllys 		cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n");
51899ebb4caSwyllys 		rc = FAILURE;
51999ebb4caSwyllys 		goto out;
52099ebb4caSwyllys 	}
52199ebb4caSwyllys 	(void) strcpy(buf1, (const char *) puent->metaslot_ks_slot);
52299ebb4caSwyllys 	*objectstore_slot_info = buf1;
52399ebb4caSwyllys 
52499ebb4caSwyllys 	buf2 = malloc(TOKEN_LABEL_SIZE);
52599ebb4caSwyllys 	if (objectstore_slot_info == NULL) {
52699ebb4caSwyllys 		cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n");
52799ebb4caSwyllys 		rc = FAILURE;
52899ebb4caSwyllys 		goto out;
52999ebb4caSwyllys 	}
53099ebb4caSwyllys 	(void) strcpy(buf2, (const char *) puent->metaslot_ks_token);
53199ebb4caSwyllys 	*objectstore_token_info = buf2;
53299ebb4caSwyllys 
53399ebb4caSwyllys out:
53499ebb4caSwyllys 	if (puent != NULL) {
53599ebb4caSwyllys 		free_uentry(puent);
53699ebb4caSwyllys 	}
53799ebb4caSwyllys 
53899ebb4caSwyllys 	if (rc == FAILURE) {
53999ebb4caSwyllys 		if (buf1 != NULL) {
54099ebb4caSwyllys 			free(buf1);
54199ebb4caSwyllys 		}
54299ebb4caSwyllys 		if (buf2 != NULL) {
54399ebb4caSwyllys 			free(buf2);
54499ebb4caSwyllys 		}
54599ebb4caSwyllys 	}
54699ebb4caSwyllys 
54799ebb4caSwyllys 	return (rc);
54899ebb4caSwyllys }
549*b5a2d845SHai-May Chao 
550*b5a2d845SHai-May Chao static CK_RV
551*b5a2d845SHai-May Chao parse_fips_mode(char *buf, int *mode)
552*b5a2d845SHai-May Chao {
553*b5a2d845SHai-May Chao 
554*b5a2d845SHai-May Chao 	char *value;
555*b5a2d845SHai-May Chao 
556*b5a2d845SHai-May Chao 	if (strncmp(buf, EF_FIPS_STATUS, sizeof (EF_FIPS_STATUS) - 1) == 0) {
557*b5a2d845SHai-May Chao 		if (value = strpbrk(buf, SEP_EQUAL)) {
558*b5a2d845SHai-May Chao 			value++; /* get rid of = */
559*b5a2d845SHai-May Chao 			if (strcmp(value, DISABLED_KEYWORD) == 0) {
560*b5a2d845SHai-May Chao 				*mode = CRYPTO_FIPS_MODE_DISABLED;
561*b5a2d845SHai-May Chao 			} else if (strcmp(value, ENABLED_KEYWORD) == 0) {
562*b5a2d845SHai-May Chao 				*mode = CRYPTO_FIPS_MODE_ENABLED;
563*b5a2d845SHai-May Chao 			} else {
564*b5a2d845SHai-May Chao 				cryptoerror(LOG_ERR,
565*b5a2d845SHai-May Chao 				    "failed to parse kcf.conf file.\n");
566*b5a2d845SHai-May Chao 				return (CKR_FUNCTION_FAILED);
567*b5a2d845SHai-May Chao 			}
568*b5a2d845SHai-May Chao 			return (CKR_OK);
569*b5a2d845SHai-May Chao 		} else {
570*b5a2d845SHai-May Chao 			return (CKR_FUNCTION_FAILED);
571*b5a2d845SHai-May Chao 		}
572*b5a2d845SHai-May Chao 	} else {
573*b5a2d845SHai-May Chao 		/* should not come here */
574*b5a2d845SHai-May Chao 		return (CKR_FUNCTION_FAILED);
575*b5a2d845SHai-May Chao 	}
576*b5a2d845SHai-May Chao 
577*b5a2d845SHai-May Chao }
578*b5a2d845SHai-May Chao 
579*b5a2d845SHai-May Chao static boolean_t
580*b5a2d845SHai-May Chao is_fips(char *name)
581*b5a2d845SHai-May Chao {
582*b5a2d845SHai-May Chao 	if (strcmp(name, FIPS_KEYWORD) == 0) {
583*b5a2d845SHai-May Chao 		return (B_TRUE);
584*b5a2d845SHai-May Chao 	} else {
585*b5a2d845SHai-May Chao 		return (B_FALSE);
586*b5a2d845SHai-May Chao 	}
587*b5a2d845SHai-May Chao }
588*b5a2d845SHai-May Chao 
589*b5a2d845SHai-May Chao CK_RV
590*b5a2d845SHai-May Chao get_fips_mode(int *mode)
591*b5a2d845SHai-May Chao {
592*b5a2d845SHai-May Chao 	FILE	*pfile = NULL;
593*b5a2d845SHai-May Chao 	char	buffer[BUFSIZ];
594*b5a2d845SHai-May Chao 	int	len;
595*b5a2d845SHai-May Chao 	CK_RV	rc = CKR_OK;
596*b5a2d845SHai-May Chao 	int found = 0;
597*b5a2d845SHai-May Chao 	char *token1;
598*b5a2d845SHai-May Chao 
599*b5a2d845SHai-May Chao 	if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) {
600*b5a2d845SHai-May Chao 		cryptoerror(LOG_ERR,
601*b5a2d845SHai-May Chao 		    "failed to open the kcf.conf file for read only.");
602*b5a2d845SHai-May Chao 		return (CKR_FUNCTION_FAILED);
603*b5a2d845SHai-May Chao 	}
604*b5a2d845SHai-May Chao 
605*b5a2d845SHai-May Chao 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
606*b5a2d845SHai-May Chao 		if (buffer[0] == '#' || buffer[0] == ' ' ||
607*b5a2d845SHai-May Chao 		    buffer[0] == '\n'|| buffer[0] == '\t') {
608*b5a2d845SHai-May Chao 			continue;   /* ignore comment lines */
609*b5a2d845SHai-May Chao 		}
610*b5a2d845SHai-May Chao 
611*b5a2d845SHai-May Chao 		len = strlen(buffer);
612*b5a2d845SHai-May Chao 		if (buffer[len - 1] == '\n') { /* get rid of trailing '\n' */
613*b5a2d845SHai-May Chao 			len--;
614*b5a2d845SHai-May Chao 		}
615*b5a2d845SHai-May Chao 		buffer[len] = '\0';
616*b5a2d845SHai-May Chao 
617*b5a2d845SHai-May Chao 		/* Get provider name */
618*b5a2d845SHai-May Chao 		if ((token1 = strtok(buffer, SEP_COLON)) ==
619*b5a2d845SHai-May Chao 		    NULL) { /* buf is NULL */
620*b5a2d845SHai-May Chao 			return (CKR_FUNCTION_FAILED);
621*b5a2d845SHai-May Chao 		};
622*b5a2d845SHai-May Chao 
623*b5a2d845SHai-May Chao 		if (is_fips(token1)) {
624*b5a2d845SHai-May Chao 			if ((rc = parse_fips_mode(buffer + strlen(token1) + 1,
625*b5a2d845SHai-May Chao 			    mode)) != CKR_OK) {
626*b5a2d845SHai-May Chao 				goto out;
627*b5a2d845SHai-May Chao 			} else {
628*b5a2d845SHai-May Chao 				found++;
629*b5a2d845SHai-May Chao 				break;
630*b5a2d845SHai-May Chao 			}
631*b5a2d845SHai-May Chao 		} else {
632*b5a2d845SHai-May Chao 			continue;
633*b5a2d845SHai-May Chao 		}
634*b5a2d845SHai-May Chao 	}
635*b5a2d845SHai-May Chao 
636*b5a2d845SHai-May Chao 	if (!found) {
637*b5a2d845SHai-May Chao 		*mode = CRYPTO_FIPS_MODE_DISABLED;
638*b5a2d845SHai-May Chao 	}
639*b5a2d845SHai-May Chao 
640*b5a2d845SHai-May Chao out:
641*b5a2d845SHai-May Chao 	(void) fclose(pfile);
642*b5a2d845SHai-May Chao 	return (rc);
643*b5a2d845SHai-May Chao }
644