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 /*
2210500SHai-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 *);
36*10979SHai-May.Chao@Sun.COM static boolean_t is_fips(char *);
370Sstevel@tonic-gate
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate * Retrieve the user-level provider info from the pkcs11.conf file.
400Sstevel@tonic-gate * If successful, the result is returned from the ppliblist argument.
410Sstevel@tonic-gate * This function returns SUCCESS if successfully done; otherwise it returns
420Sstevel@tonic-gate * FAILURE.
430Sstevel@tonic-gate */
440Sstevel@tonic-gate int
get_pkcs11conf_info(uentrylist_t ** ppliblist)450Sstevel@tonic-gate get_pkcs11conf_info(uentrylist_t **ppliblist)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate FILE *pfile;
480Sstevel@tonic-gate char buffer[BUFSIZ];
490Sstevel@tonic-gate size_t len;
500Sstevel@tonic-gate uentry_t *pent;
510Sstevel@tonic-gate uentrylist_t *pentlist;
520Sstevel@tonic-gate uentrylist_t *pcur;
530Sstevel@tonic-gate int rc = SUCCESS;
540Sstevel@tonic-gate
550Sstevel@tonic-gate *ppliblist = NULL;
561914Scasper if ((pfile = fopen(_PATH_PKCS11_CONF, "rF")) == NULL) {
570Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_PKCS11_CONF);
580Sstevel@tonic-gate return (FAILURE);
590Sstevel@tonic-gate }
600Sstevel@tonic-gate
610Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) {
620Sstevel@tonic-gate if (buffer[0] == '#' || buffer[0] == ' ' ||
630Sstevel@tonic-gate buffer[0] == '\n'|| buffer[0] == '\t') {
640Sstevel@tonic-gate continue; /* ignore comment lines */
650Sstevel@tonic-gate }
660Sstevel@tonic-gate
670Sstevel@tonic-gate len = strlen(buffer);
680Sstevel@tonic-gate if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
690Sstevel@tonic-gate len--;
700Sstevel@tonic-gate }
710Sstevel@tonic-gate buffer[len] = '\0';
720Sstevel@tonic-gate
730Sstevel@tonic-gate if ((rc = uef_interpret(buffer, &pent)) != SUCCESS) {
740Sstevel@tonic-gate break;
750Sstevel@tonic-gate }
760Sstevel@tonic-gate
770Sstevel@tonic-gate /* append pent into ppliblist */
780Sstevel@tonic-gate pentlist = malloc(sizeof (uentrylist_t));
790Sstevel@tonic-gate if (pentlist == NULL) {
800Sstevel@tonic-gate cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
810Sstevel@tonic-gate _PATH_PKCS11_CONF);
820Sstevel@tonic-gate free_uentry(pent);
830Sstevel@tonic-gate rc = FAILURE;
840Sstevel@tonic-gate break;
850Sstevel@tonic-gate }
860Sstevel@tonic-gate pentlist->puent = pent;
870Sstevel@tonic-gate pentlist->next = NULL;
880Sstevel@tonic-gate
890Sstevel@tonic-gate if (*ppliblist == NULL) {
900Sstevel@tonic-gate *ppliblist = pcur = pentlist;
910Sstevel@tonic-gate } else {
920Sstevel@tonic-gate pcur->next = pentlist;
930Sstevel@tonic-gate pcur = pcur->next;
940Sstevel@tonic-gate }
950Sstevel@tonic-gate }
960Sstevel@tonic-gate
970Sstevel@tonic-gate (void) fclose(pfile);
980Sstevel@tonic-gate
990Sstevel@tonic-gate if (rc != SUCCESS) {
1000Sstevel@tonic-gate free_uentrylist(*ppliblist);
1010Sstevel@tonic-gate *ppliblist = NULL;
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate return (rc);
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate
107*10979SHai-May.Chao@Sun.COM static int
parse_fips_mode(char * buf,boolean_t * mode)108*10979SHai-May.Chao@Sun.COM parse_fips_mode(char *buf, boolean_t *mode)
109*10979SHai-May.Chao@Sun.COM {
110*10979SHai-May.Chao@Sun.COM char *value;
111*10979SHai-May.Chao@Sun.COM
112*10979SHai-May.Chao@Sun.COM if (strncmp(buf, EF_FIPS_STATUS, sizeof (EF_FIPS_STATUS) - 1) == 0) {
113*10979SHai-May.Chao@Sun.COM if (value = strpbrk(buf, SEP_EQUAL)) {
114*10979SHai-May.Chao@Sun.COM value++; /* get rid of = */
115*10979SHai-May.Chao@Sun.COM if (strcmp(value, DISABLED_KEYWORD) == 0) {
116*10979SHai-May.Chao@Sun.COM *mode = B_FALSE;
117*10979SHai-May.Chao@Sun.COM } else if (strcmp(value, ENABLED_KEYWORD) == 0) {
118*10979SHai-May.Chao@Sun.COM *mode = B_TRUE;
119*10979SHai-May.Chao@Sun.COM } else {
120*10979SHai-May.Chao@Sun.COM cryptoerror(LOG_ERR, gettext(
121*10979SHai-May.Chao@Sun.COM "Failed to parse pkcs11.conf file.\n"));
122*10979SHai-May.Chao@Sun.COM return (CKR_FUNCTION_FAILED);
123*10979SHai-May.Chao@Sun.COM }
124*10979SHai-May.Chao@Sun.COM return (CKR_OK);
125*10979SHai-May.Chao@Sun.COM } else {
126*10979SHai-May.Chao@Sun.COM return (CKR_FUNCTION_FAILED);
127*10979SHai-May.Chao@Sun.COM }
128*10979SHai-May.Chao@Sun.COM } else {
129*10979SHai-May.Chao@Sun.COM /* should not come here */
130*10979SHai-May.Chao@Sun.COM cryptoerror(LOG_ERR, gettext(
131*10979SHai-May.Chao@Sun.COM "Failed to parse pkcs11.conf file.\n"));
132*10979SHai-May.Chao@Sun.COM return (CKR_FUNCTION_FAILED);
133*10979SHai-May.Chao@Sun.COM }
134*10979SHai-May.Chao@Sun.COM
135*10979SHai-May.Chao@Sun.COM }
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate /*
1380Sstevel@tonic-gate * This routine converts a char string into a uentry_t structure
1390Sstevel@tonic-gate * The input string "buf" should be one of the following:
1400Sstevel@tonic-gate * library_name
1410Sstevel@tonic-gate * library_name:NO_RANDOM
1420Sstevel@tonic-gate * library_name:disabledlist=m1,m2,...,mk
1430Sstevel@tonic-gate * library_name:disabledlist=m1,m2,...,mk;NO_RANDOM
1440Sstevel@tonic-gate * library_name:enabledlist=
1450Sstevel@tonic-gate * library_name:enabledlist=;NO_RANDOM
1460Sstevel@tonic-gate * library_name:enabledlist=m1,m2,...,mk
1470Sstevel@tonic-gate * library_name:enabledlist=m1,m2,...,mk;NO_RANDOM
1480Sstevel@tonic-gate * metaslot:status=enabled;enabledlist=m1,m2,....;slot=<slot-description>;\
1490Sstevel@tonic-gate * token=<token-label>
1500Sstevel@tonic-gate *
1510Sstevel@tonic-gate * Note:
1520Sstevel@tonic-gate * The mechanisms m1,..mk are in hex form. For example, "0x00000210"
1530Sstevel@tonic-gate * for CKM_MD5.
1540Sstevel@tonic-gate *
1550Sstevel@tonic-gate * For the metaslot entry, "enabledlist", "slot", "auto_key_migrate"
1560Sstevel@tonic-gate * or "token" is optional
1570Sstevel@tonic-gate */
1580Sstevel@tonic-gate static int
uef_interpret(char * buf,uentry_t ** ppent)1590Sstevel@tonic-gate uef_interpret(char *buf, uentry_t **ppent)
1600Sstevel@tonic-gate {
1610Sstevel@tonic-gate uentry_t *pent;
1620Sstevel@tonic-gate char *token1;
1630Sstevel@tonic-gate char *token2;
1640Sstevel@tonic-gate char *lasts;
1650Sstevel@tonic-gate int rc;
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate *ppent = NULL;
1680Sstevel@tonic-gate if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) {
1690Sstevel@tonic-gate /* buf is NULL */
1700Sstevel@tonic-gate return (FAILURE);
1710Sstevel@tonic-gate };
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate pent = calloc(sizeof (uentry_t), 1);
1740Sstevel@tonic-gate if (pent == NULL) {
1750Sstevel@tonic-gate cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
1760Sstevel@tonic-gate _PATH_PKCS11_CONF);
1770Sstevel@tonic-gate return (FAILURE);
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate (void) strlcpy(pent->name, token1, sizeof (pent->name));
180*10979SHai-May.Chao@Sun.COM
181*10979SHai-May.Chao@Sun.COM if (is_fips(token1)) {
182*10979SHai-May.Chao@Sun.COM if ((rc = parse_fips_mode(buf + strlen(token1) + 1,
183*10979SHai-May.Chao@Sun.COM &pent->flag_fips_enabled)) != SUCCESS) {
184*10979SHai-May.Chao@Sun.COM free_uentry(pent);
185*10979SHai-May.Chao@Sun.COM return (rc);
186*10979SHai-May.Chao@Sun.COM }
187*10979SHai-May.Chao@Sun.COM
188*10979SHai-May.Chao@Sun.COM *ppent = pent;
189*10979SHai-May.Chao@Sun.COM return (SUCCESS);
190*10979SHai-May.Chao@Sun.COM }
191*10979SHai-May.Chao@Sun.COM
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate * in case metaslot_auto_key_migrate is not specified, it should
1940Sstevel@tonic-gate * be default to true
1950Sstevel@tonic-gate */
1960Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_TRUE;
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate while ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) != NULL) {
1990Sstevel@tonic-gate if ((rc = parse_policylist(token2, pent)) != SUCCESS) {
2000Sstevel@tonic-gate free_uentry(pent);
2010Sstevel@tonic-gate return (rc);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate *ppent = pent;
2060Sstevel@tonic-gate return (SUCCESS);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate /*
2110Sstevel@tonic-gate * This routine parses the policy list and stored the result in the argument
2120Sstevel@tonic-gate * pent.
2130Sstevel@tonic-gate *
2140Sstevel@tonic-gate * Arg buf: input only, its format should be one of the following:
2150Sstevel@tonic-gate * enabledlist=
2160Sstevel@tonic-gate * enabledlist=m1,m2,...,mk
2170Sstevel@tonic-gate * disabledlist=m1,m2,...,mk
2180Sstevel@tonic-gate * NO_RANDOM
2190Sstevel@tonic-gate * metaslot_status=enabled|disabled
2200Sstevel@tonic-gate * metaslot_token=<token-label>
2210Sstevel@tonic-gate * metaslot_slot=<slot-description.
2220Sstevel@tonic-gate *
2230Sstevel@tonic-gate * Arg pent: input/output
2240Sstevel@tonic-gate *
2250Sstevel@tonic-gate * return: SUCCESS or FAILURE
2260Sstevel@tonic-gate */
2270Sstevel@tonic-gate static int
parse_policylist(char * buf,uentry_t * pent)2280Sstevel@tonic-gate parse_policylist(char *buf, uentry_t *pent)
2290Sstevel@tonic-gate {
2300Sstevel@tonic-gate umechlist_t *phead = NULL;
2310Sstevel@tonic-gate umechlist_t *pcur = NULL;
2320Sstevel@tonic-gate umechlist_t *pmech;
2330Sstevel@tonic-gate char *next_token;
2340Sstevel@tonic-gate char *value;
2350Sstevel@tonic-gate char *lasts;
2360Sstevel@tonic-gate int count = 0;
2370Sstevel@tonic-gate int rc = SUCCESS;
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate if (pent == NULL) {
2400Sstevel@tonic-gate return (FAILURE);
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate if (strncmp(buf, EF_DISABLED, sizeof (EF_DISABLED) - 1) == 0) {
2440Sstevel@tonic-gate pent->flag_enabledlist = B_FALSE;
2450Sstevel@tonic-gate } else if (strncmp(buf, EF_ENABLED, sizeof (EF_ENABLED) - 1) == 0) {
2460Sstevel@tonic-gate pent->flag_enabledlist = B_TRUE;
2470Sstevel@tonic-gate } else if (strncmp(buf, EF_NORANDOM, sizeof (EF_NORANDOM) - 1) == 0) {
2480Sstevel@tonic-gate pent->flag_norandom = B_TRUE;
2490Sstevel@tonic-gate return (rc);
2500Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_TOKEN,
2510Sstevel@tonic-gate sizeof (METASLOT_TOKEN) - 1) == 0) {
2520Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) {
2530Sstevel@tonic-gate value++; /* get rid of = */
2540Sstevel@tonic-gate (void) strlcpy((char *)pent->metaslot_ks_token, value,
2553089Swyllys sizeof (pent->metaslot_ks_token));
2560Sstevel@tonic-gate return (SUCCESS);
2570Sstevel@tonic-gate } else {
2580Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n",
2590Sstevel@tonic-gate _PATH_PKCS11_CONF);
2600Sstevel@tonic-gate return (FAILURE);
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_SLOT,
2630Sstevel@tonic-gate sizeof (METASLOT_SLOT) - 1) == 0) {
2640Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) {
2650Sstevel@tonic-gate value++; /* get rid of = */
2660Sstevel@tonic-gate (void) strlcpy((char *)pent->metaslot_ks_slot, value,
2673089Swyllys sizeof (pent->metaslot_ks_slot));
2680Sstevel@tonic-gate return (SUCCESS);
2690Sstevel@tonic-gate } else {
2700Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n",
2710Sstevel@tonic-gate _PATH_PKCS11_CONF);
2720Sstevel@tonic-gate return (FAILURE);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_STATUS,
2750Sstevel@tonic-gate sizeof (METASLOT_STATUS) - 1) == 0) {
2760Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) {
2770Sstevel@tonic-gate value++; /* get rid of = */
27810500SHai-May.Chao@Sun.COM if (strcmp(value, DISABLED_KEYWORD) == 0) {
2790Sstevel@tonic-gate pent->flag_metaslot_enabled = B_FALSE;
28010500SHai-May.Chao@Sun.COM } else if (strcmp(value, ENABLED_KEYWORD) == 0) {
2810Sstevel@tonic-gate pent->flag_metaslot_enabled = B_TRUE;
2820Sstevel@tonic-gate } else {
2830Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n",
2840Sstevel@tonic-gate _PATH_PKCS11_CONF);
2850Sstevel@tonic-gate return (FAILURE);
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate return (SUCCESS);
2880Sstevel@tonic-gate } else {
2890Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n",
2900Sstevel@tonic-gate _PATH_PKCS11_CONF);
2910Sstevel@tonic-gate return (FAILURE);
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_AUTO_KEY_MIGRATE,
2940Sstevel@tonic-gate sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) {
2950Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) {
2960Sstevel@tonic-gate value++; /* get rid of = */
29710500SHai-May.Chao@Sun.COM if (strcmp(value, DISABLED_KEYWORD) == 0) {
2980Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_FALSE;
29910500SHai-May.Chao@Sun.COM } else if (strcmp(value, ENABLED_KEYWORD) == 0) {
3000Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_TRUE;
3010Sstevel@tonic-gate } else {
3020Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n",
3030Sstevel@tonic-gate _PATH_PKCS11_CONF);
3040Sstevel@tonic-gate return (FAILURE);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate return (SUCCESS);
3070Sstevel@tonic-gate } else {
3080Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n",
3090Sstevel@tonic-gate _PATH_PKCS11_CONF);
3100Sstevel@tonic-gate return (FAILURE);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate } else {
3130Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n",
3140Sstevel@tonic-gate _PATH_PKCS11_CONF);
3150Sstevel@tonic-gate return (FAILURE);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) {
3190Sstevel@tonic-gate value++; /* get rid of = */
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate if ((next_token = strtok_r(value, SEP_COMMA, &lasts)) == NULL) {
3230Sstevel@tonic-gate if (pent->flag_enabledlist) {
3240Sstevel@tonic-gate return (SUCCESS);
3250Sstevel@tonic-gate } else {
3260Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n",
3270Sstevel@tonic-gate _PATH_PKCS11_CONF);
3280Sstevel@tonic-gate return (FAILURE);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate while (next_token) {
3330Sstevel@tonic-gate if ((pmech = create_umech(next_token)) == NULL) {
3340Sstevel@tonic-gate cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
3350Sstevel@tonic-gate _PATH_PKCS11_CONF);
3360Sstevel@tonic-gate rc = FAILURE;
3370Sstevel@tonic-gate break;
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate if (phead == NULL) {
3410Sstevel@tonic-gate phead = pcur = pmech;
3420Sstevel@tonic-gate } else {
3430Sstevel@tonic-gate pcur->next = pmech;
3440Sstevel@tonic-gate pcur = pcur->next;
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate count++;
3470Sstevel@tonic-gate next_token = strtok_r(NULL, SEP_COMMA, &lasts);
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate if (rc == SUCCESS) {
3510Sstevel@tonic-gate pent->policylist = phead;
3520Sstevel@tonic-gate pent->count = count;
3530Sstevel@tonic-gate } else {
3540Sstevel@tonic-gate free_umechlist(phead);
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate return (rc);
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate /*
3620Sstevel@tonic-gate * Create one item of type umechlist_t with the mechanism name. A NULL is
3630Sstevel@tonic-gate * returned when the input name is NULL or the heap memory is insufficient.
3640Sstevel@tonic-gate */
3650Sstevel@tonic-gate umechlist_t *
create_umech(char * name)3660Sstevel@tonic-gate create_umech(char *name)
3670Sstevel@tonic-gate {
3680Sstevel@tonic-gate umechlist_t *pmech = NULL;
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate if (name == NULL) {
3710Sstevel@tonic-gate return (NULL);
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate if ((pmech = malloc(sizeof (umechlist_t))) != NULL) {
3750Sstevel@tonic-gate (void) strlcpy(pmech->name, name, sizeof (pmech->name));
3760Sstevel@tonic-gate pmech->next = NULL;
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate return (pmech);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate void
free_umechlist(umechlist_t * plist)3840Sstevel@tonic-gate free_umechlist(umechlist_t *plist)
3850Sstevel@tonic-gate {
3860Sstevel@tonic-gate umechlist_t *pnext;
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate while (plist != NULL) {
3890Sstevel@tonic-gate pnext = plist->next;
3900Sstevel@tonic-gate free(plist);
3910Sstevel@tonic-gate plist = pnext;
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate void
free_uentry(uentry_t * pent)3970Sstevel@tonic-gate free_uentry(uentry_t *pent)
3980Sstevel@tonic-gate {
3990Sstevel@tonic-gate if (pent == NULL) {
4000Sstevel@tonic-gate return;
4010Sstevel@tonic-gate } else {
4020Sstevel@tonic-gate free_umechlist(pent->policylist);
4030Sstevel@tonic-gate free(pent);
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate void
free_uentrylist(uentrylist_t * entrylist)4090Sstevel@tonic-gate free_uentrylist(uentrylist_t *entrylist)
4100Sstevel@tonic-gate {
4110Sstevel@tonic-gate uentrylist_t *pnext;
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate while (entrylist != NULL) {
4140Sstevel@tonic-gate pnext = entrylist->next;
4150Sstevel@tonic-gate free_uentry(entrylist->puent);
4160Sstevel@tonic-gate free(entrylist);
4170Sstevel@tonic-gate entrylist = pnext;
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate }
4203089Swyllys
4213089Swyllys
4223089Swyllys
4233089Swyllys /*
4243089Swyllys * Duplicate an UEF mechanism list. A NULL pointer is returned if out of
4253089Swyllys * memory or the input argument is NULL.
4263089Swyllys */
4273089Swyllys static umechlist_t *
dup_umechlist(umechlist_t * plist)4283089Swyllys dup_umechlist(umechlist_t *plist)
4293089Swyllys {
4303089Swyllys umechlist_t *pres = NULL;
4313089Swyllys umechlist_t *pcur;
4323089Swyllys umechlist_t *ptmp;
4333089Swyllys int rc = SUCCESS;
4343089Swyllys
4353089Swyllys while (plist != NULL) {
4363089Swyllys if (!(ptmp = create_umech(plist->name))) {
4373089Swyllys rc = FAILURE;
4383089Swyllys break;
4393089Swyllys }
4403089Swyllys
4413089Swyllys if (pres == NULL) {
4423089Swyllys pres = pcur = ptmp;
4433089Swyllys } else {
4443089Swyllys pcur->next = ptmp;
4453089Swyllys pcur = pcur->next;
4463089Swyllys }
4473089Swyllys plist = plist->next;
4483089Swyllys }
4493089Swyllys
4503089Swyllys if (rc != SUCCESS) {
4513089Swyllys free_umechlist(pres);
4523089Swyllys return (NULL);
4533089Swyllys }
4543089Swyllys
4553089Swyllys return (pres);
4563089Swyllys }
4573089Swyllys
4583089Swyllys
4593089Swyllys /*
4603089Swyllys * Duplicate an uentry. A NULL pointer is returned if out of memory
4613089Swyllys * or the input argument is NULL.
4623089Swyllys */
4633089Swyllys static uentry_t *
dup_uentry(uentry_t * puent1)4643089Swyllys dup_uentry(uentry_t *puent1)
4653089Swyllys {
4663089Swyllys uentry_t *puent2 = NULL;
4673089Swyllys
4683089Swyllys if (puent1 == NULL) {
4693089Swyllys return (NULL);
4703089Swyllys }
4713089Swyllys
4723089Swyllys if ((puent2 = malloc(sizeof (uentry_t))) == NULL) {
4733089Swyllys cryptoerror(LOG_STDERR, gettext("out of memory."));
4743089Swyllys return (NULL);
4753089Swyllys } else {
4763089Swyllys (void) strlcpy(puent2->name, puent1->name,
4773089Swyllys sizeof (puent2->name));
4783089Swyllys puent2->flag_norandom = puent1->flag_norandom;
4793089Swyllys puent2->flag_enabledlist = puent1->flag_enabledlist;
4803089Swyllys puent2->policylist = dup_umechlist(puent1->policylist);
4813089Swyllys puent2->flag_metaslot_enabled = puent1->flag_metaslot_enabled;
4823089Swyllys puent2->flag_metaslot_auto_key_migrate
4833089Swyllys = puent1->flag_metaslot_auto_key_migrate;
4843089Swyllys (void) memcpy(puent2->metaslot_ks_slot,
4853089Swyllys puent1->metaslot_ks_slot, SLOT_DESCRIPTION_SIZE);
4863089Swyllys (void) memcpy(puent2->metaslot_ks_token,
4873089Swyllys puent1->metaslot_ks_token, TOKEN_LABEL_SIZE);
4883089Swyllys puent2->count = puent1->count;
489*10979SHai-May.Chao@Sun.COM puent2->flag_fips_enabled = puent1->flag_fips_enabled;
4903089Swyllys return (puent2);
4913089Swyllys }
4923089Swyllys }
4933089Swyllys
4943089Swyllys /*
4953089Swyllys * Find the entry in the "pkcs11.conf" file with "libname" as the provider
4963089Swyllys * name. Return the entry if found, otherwise return NULL.
4973089Swyllys */
4983089Swyllys uentry_t *
getent_uef(char * libname)4993089Swyllys getent_uef(char *libname)
5003089Swyllys {
5013089Swyllys uentrylist_t *pliblist = NULL;
5023089Swyllys uentrylist_t *plib = NULL;
5033089Swyllys uentry_t *puent = NULL;
5043089Swyllys boolean_t found = B_FALSE;
5053089Swyllys
5063089Swyllys if (libname == NULL) {
5073089Swyllys return (NULL);
5083089Swyllys }
5093089Swyllys
5103089Swyllys if ((get_pkcs11conf_info(&pliblist)) == FAILURE) {
5113089Swyllys return (NULL);
5123089Swyllys }
5133089Swyllys
5143089Swyllys plib = pliblist;
5153089Swyllys while (plib) {
5163089Swyllys if (strcmp(plib->puent->name, libname) == 0) {
5173089Swyllys found = B_TRUE;
5183089Swyllys break;
5193089Swyllys } else {
5203089Swyllys plib = plib->next;
5213089Swyllys }
5223089Swyllys }
5233089Swyllys
5243089Swyllys if (found) {
5253089Swyllys puent = dup_uentry(plib->puent);
5263089Swyllys }
5273089Swyllys
5283089Swyllys free_uentrylist(pliblist);
5293089Swyllys return (puent);
5303089Swyllys }
5313089Swyllys
5323089Swyllys
5333089Swyllys
5343089Swyllys /*
5353089Swyllys * Retrieve the metaslot information from the pkcs11.conf file.
5363089Swyllys * This function returns SUCCESS if successfully done; otherwise it returns
5373089Swyllys * FAILURE. If successful, the caller is responsible to free the space
5383089Swyllys * allocated for objectstore_slot_info and objectstore_token_info.
5393089Swyllys */
5403089Swyllys int
get_metaslot_info(boolean_t * status_enabled,boolean_t * migrate_enabled,char ** objectstore_slot_info,char ** objectstore_token_info)5413089Swyllys get_metaslot_info(boolean_t *status_enabled, boolean_t *migrate_enabled,
5423089Swyllys char **objectstore_slot_info, char **objectstore_token_info)
5433089Swyllys {
5443089Swyllys
5453089Swyllys int rc = SUCCESS;
5463089Swyllys uentry_t *puent;
5473089Swyllys char *buf1 = NULL;
5483089Swyllys char *buf2 = NULL;
5493089Swyllys
5503089Swyllys if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
5513089Swyllys /* metaslot entry doesn't exist */
5523089Swyllys return (FAILURE);
5533089Swyllys }
5543089Swyllys
5553089Swyllys *status_enabled = puent->flag_metaslot_enabled;
5563089Swyllys *migrate_enabled = puent->flag_metaslot_auto_key_migrate;
5573089Swyllys
5583089Swyllys buf1 = malloc(SLOT_DESCRIPTION_SIZE);
5593089Swyllys if (buf1 == NULL) {
5603089Swyllys cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n");
5613089Swyllys rc = FAILURE;
5623089Swyllys goto out;
5633089Swyllys }
5643089Swyllys (void) strcpy(buf1, (const char *) puent->metaslot_ks_slot);
5653089Swyllys *objectstore_slot_info = buf1;
5663089Swyllys
5673089Swyllys buf2 = malloc(TOKEN_LABEL_SIZE);
5683089Swyllys if (objectstore_slot_info == NULL) {
5693089Swyllys cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n");
5703089Swyllys rc = FAILURE;
5713089Swyllys goto out;
5723089Swyllys }
5733089Swyllys (void) strcpy(buf2, (const char *) puent->metaslot_ks_token);
5743089Swyllys *objectstore_token_info = buf2;
5753089Swyllys
5763089Swyllys out:
5773089Swyllys if (puent != NULL) {
5783089Swyllys free_uentry(puent);
5793089Swyllys }
5803089Swyllys
5813089Swyllys if (rc == FAILURE) {
5823089Swyllys if (buf1 != NULL) {
5833089Swyllys free(buf1);
5843089Swyllys }
5853089Swyllys if (buf2 != NULL) {
5863089Swyllys free(buf2);
5873089Swyllys }
5883089Swyllys }
5893089Swyllys
5903089Swyllys return (rc);
5913089Swyllys }
59210500SHai-May.Chao@Sun.COM
59310500SHai-May.Chao@Sun.COM static boolean_t
is_fips(char * name)59410500SHai-May.Chao@Sun.COM is_fips(char *name)
59510500SHai-May.Chao@Sun.COM {
59610500SHai-May.Chao@Sun.COM if (strcmp(name, FIPS_KEYWORD) == 0) {
59710500SHai-May.Chao@Sun.COM return (B_TRUE);
59810500SHai-May.Chao@Sun.COM } else {
59910500SHai-May.Chao@Sun.COM return (B_FALSE);
60010500SHai-May.Chao@Sun.COM }
60110500SHai-May.Chao@Sun.COM }
60210500SHai-May.Chao@Sun.COM
60310500SHai-May.Chao@Sun.COM CK_RV
get_fips_mode(int * mode)60410500SHai-May.Chao@Sun.COM get_fips_mode(int *mode)
60510500SHai-May.Chao@Sun.COM {
60610500SHai-May.Chao@Sun.COM FILE *pfile = NULL;
60710500SHai-May.Chao@Sun.COM char buffer[BUFSIZ];
60810500SHai-May.Chao@Sun.COM int len;
60910500SHai-May.Chao@Sun.COM CK_RV rc = CKR_OK;
61010500SHai-May.Chao@Sun.COM int found = 0;
61110500SHai-May.Chao@Sun.COM char *token1;
612*10979SHai-May.Chao@Sun.COM boolean_t fips_mode = B_FALSE;
61310500SHai-May.Chao@Sun.COM
614*10979SHai-May.Chao@Sun.COM if ((pfile = fopen(_PATH_PKCS11_CONF, "r")) == NULL) {
61510584SHai-May.Chao@Sun.COM cryptoerror(LOG_DEBUG,
616*10979SHai-May.Chao@Sun.COM "failed to open the pkcs11.conf file for read only.");
61710584SHai-May.Chao@Sun.COM *mode = CRYPTO_FIPS_MODE_DISABLED;
61810584SHai-May.Chao@Sun.COM return (CKR_OK);
61910500SHai-May.Chao@Sun.COM }
62010500SHai-May.Chao@Sun.COM
62110500SHai-May.Chao@Sun.COM while (fgets(buffer, BUFSIZ, pfile) != NULL) {
62210500SHai-May.Chao@Sun.COM if (buffer[0] == '#' || buffer[0] == ' ' ||
62310500SHai-May.Chao@Sun.COM buffer[0] == '\n'|| buffer[0] == '\t') {
62410500SHai-May.Chao@Sun.COM continue; /* ignore comment lines */
62510500SHai-May.Chao@Sun.COM }
62610500SHai-May.Chao@Sun.COM
62710500SHai-May.Chao@Sun.COM len = strlen(buffer);
62810500SHai-May.Chao@Sun.COM if (buffer[len - 1] == '\n') { /* get rid of trailing '\n' */
62910500SHai-May.Chao@Sun.COM len--;
63010500SHai-May.Chao@Sun.COM }
63110500SHai-May.Chao@Sun.COM buffer[len] = '\0';
63210500SHai-May.Chao@Sun.COM
63310500SHai-May.Chao@Sun.COM /* Get provider name */
63410500SHai-May.Chao@Sun.COM if ((token1 = strtok(buffer, SEP_COLON)) ==
63510500SHai-May.Chao@Sun.COM NULL) { /* buf is NULL */
63610500SHai-May.Chao@Sun.COM return (CKR_FUNCTION_FAILED);
63710500SHai-May.Chao@Sun.COM };
63810500SHai-May.Chao@Sun.COM
63910500SHai-May.Chao@Sun.COM if (is_fips(token1)) {
64010500SHai-May.Chao@Sun.COM if ((rc = parse_fips_mode(buffer + strlen(token1) + 1,
641*10979SHai-May.Chao@Sun.COM &fips_mode)) != CKR_OK) {
64210500SHai-May.Chao@Sun.COM goto out;
64310500SHai-May.Chao@Sun.COM } else {
64410500SHai-May.Chao@Sun.COM found++;
645*10979SHai-May.Chao@Sun.COM if (fips_mode == B_TRUE)
646*10979SHai-May.Chao@Sun.COM *mode = CRYPTO_FIPS_MODE_ENABLED;
647*10979SHai-May.Chao@Sun.COM else
648*10979SHai-May.Chao@Sun.COM *mode = CRYPTO_FIPS_MODE_DISABLED;
64910500SHai-May.Chao@Sun.COM break;
65010500SHai-May.Chao@Sun.COM }
65110500SHai-May.Chao@Sun.COM } else {
65210500SHai-May.Chao@Sun.COM continue;
65310500SHai-May.Chao@Sun.COM }
65410500SHai-May.Chao@Sun.COM }
65510500SHai-May.Chao@Sun.COM
65610500SHai-May.Chao@Sun.COM if (!found) {
65710500SHai-May.Chao@Sun.COM *mode = CRYPTO_FIPS_MODE_DISABLED;
65810500SHai-May.Chao@Sun.COM }
65910500SHai-May.Chao@Sun.COM
66010500SHai-May.Chao@Sun.COM out:
66110500SHai-May.Chao@Sun.COM (void) fclose(pfile);
66210500SHai-May.Chao@Sun.COM return (rc);
66310500SHai-May.Chao@Sun.COM }
664