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 *); 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 = */ 23610500SHai-May.Chao@Sun.COM if (strcmp(value, DISABLED_KEYWORD) == 0) { 2370Sstevel@tonic-gate pent->flag_metaslot_enabled = B_FALSE; 23810500SHai-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 = */ 25510500SHai-May.Chao@Sun.COM if (strcmp(value, DISABLED_KEYWORD) == 0) { 2560Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_FALSE; 25710500SHai-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 } 54910500SHai-May.Chao@Sun.COM 55010500SHai-May.Chao@Sun.COM static CK_RV 55110500SHai-May.Chao@Sun.COM parse_fips_mode(char *buf, int *mode) 55210500SHai-May.Chao@Sun.COM { 55310500SHai-May.Chao@Sun.COM 55410500SHai-May.Chao@Sun.COM char *value; 55510500SHai-May.Chao@Sun.COM 55610500SHai-May.Chao@Sun.COM if (strncmp(buf, EF_FIPS_STATUS, sizeof (EF_FIPS_STATUS) - 1) == 0) { 55710500SHai-May.Chao@Sun.COM if (value = strpbrk(buf, SEP_EQUAL)) { 55810500SHai-May.Chao@Sun.COM value++; /* get rid of = */ 55910500SHai-May.Chao@Sun.COM if (strcmp(value, DISABLED_KEYWORD) == 0) { 56010500SHai-May.Chao@Sun.COM *mode = CRYPTO_FIPS_MODE_DISABLED; 56110500SHai-May.Chao@Sun.COM } else if (strcmp(value, ENABLED_KEYWORD) == 0) { 56210500SHai-May.Chao@Sun.COM *mode = CRYPTO_FIPS_MODE_ENABLED; 56310500SHai-May.Chao@Sun.COM } else { 56410500SHai-May.Chao@Sun.COM cryptoerror(LOG_ERR, 56510500SHai-May.Chao@Sun.COM "failed to parse kcf.conf file.\n"); 56610500SHai-May.Chao@Sun.COM return (CKR_FUNCTION_FAILED); 56710500SHai-May.Chao@Sun.COM } 56810500SHai-May.Chao@Sun.COM return (CKR_OK); 56910500SHai-May.Chao@Sun.COM } else { 57010500SHai-May.Chao@Sun.COM return (CKR_FUNCTION_FAILED); 57110500SHai-May.Chao@Sun.COM } 57210500SHai-May.Chao@Sun.COM } else { 57310500SHai-May.Chao@Sun.COM /* should not come here */ 57410500SHai-May.Chao@Sun.COM return (CKR_FUNCTION_FAILED); 57510500SHai-May.Chao@Sun.COM } 57610500SHai-May.Chao@Sun.COM 57710500SHai-May.Chao@Sun.COM } 57810500SHai-May.Chao@Sun.COM 57910500SHai-May.Chao@Sun.COM static boolean_t 58010500SHai-May.Chao@Sun.COM is_fips(char *name) 58110500SHai-May.Chao@Sun.COM { 58210500SHai-May.Chao@Sun.COM if (strcmp(name, FIPS_KEYWORD) == 0) { 58310500SHai-May.Chao@Sun.COM return (B_TRUE); 58410500SHai-May.Chao@Sun.COM } else { 58510500SHai-May.Chao@Sun.COM return (B_FALSE); 58610500SHai-May.Chao@Sun.COM } 58710500SHai-May.Chao@Sun.COM } 58810500SHai-May.Chao@Sun.COM 58910500SHai-May.Chao@Sun.COM CK_RV 59010500SHai-May.Chao@Sun.COM get_fips_mode(int *mode) 59110500SHai-May.Chao@Sun.COM { 59210500SHai-May.Chao@Sun.COM FILE *pfile = NULL; 59310500SHai-May.Chao@Sun.COM char buffer[BUFSIZ]; 59410500SHai-May.Chao@Sun.COM int len; 59510500SHai-May.Chao@Sun.COM CK_RV rc = CKR_OK; 59610500SHai-May.Chao@Sun.COM int found = 0; 59710500SHai-May.Chao@Sun.COM char *token1; 59810500SHai-May.Chao@Sun.COM 59910500SHai-May.Chao@Sun.COM if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) { 600*10584SHai-May.Chao@Sun.COM cryptoerror(LOG_DEBUG, 60110500SHai-May.Chao@Sun.COM "failed to open the kcf.conf file for read only."); 602*10584SHai-May.Chao@Sun.COM *mode = CRYPTO_FIPS_MODE_DISABLED; 603*10584SHai-May.Chao@Sun.COM return (CKR_OK); 60410500SHai-May.Chao@Sun.COM } 60510500SHai-May.Chao@Sun.COM 60610500SHai-May.Chao@Sun.COM while (fgets(buffer, BUFSIZ, pfile) != NULL) { 60710500SHai-May.Chao@Sun.COM if (buffer[0] == '#' || buffer[0] == ' ' || 60810500SHai-May.Chao@Sun.COM buffer[0] == '\n'|| buffer[0] == '\t') { 60910500SHai-May.Chao@Sun.COM continue; /* ignore comment lines */ 61010500SHai-May.Chao@Sun.COM } 61110500SHai-May.Chao@Sun.COM 61210500SHai-May.Chao@Sun.COM len = strlen(buffer); 61310500SHai-May.Chao@Sun.COM if (buffer[len - 1] == '\n') { /* get rid of trailing '\n' */ 61410500SHai-May.Chao@Sun.COM len--; 61510500SHai-May.Chao@Sun.COM } 61610500SHai-May.Chao@Sun.COM buffer[len] = '\0'; 61710500SHai-May.Chao@Sun.COM 61810500SHai-May.Chao@Sun.COM /* Get provider name */ 61910500SHai-May.Chao@Sun.COM if ((token1 = strtok(buffer, SEP_COLON)) == 62010500SHai-May.Chao@Sun.COM NULL) { /* buf is NULL */ 62110500SHai-May.Chao@Sun.COM return (CKR_FUNCTION_FAILED); 62210500SHai-May.Chao@Sun.COM }; 62310500SHai-May.Chao@Sun.COM 62410500SHai-May.Chao@Sun.COM if (is_fips(token1)) { 62510500SHai-May.Chao@Sun.COM if ((rc = parse_fips_mode(buffer + strlen(token1) + 1, 62610500SHai-May.Chao@Sun.COM mode)) != CKR_OK) { 62710500SHai-May.Chao@Sun.COM goto out; 62810500SHai-May.Chao@Sun.COM } else { 62910500SHai-May.Chao@Sun.COM found++; 63010500SHai-May.Chao@Sun.COM break; 63110500SHai-May.Chao@Sun.COM } 63210500SHai-May.Chao@Sun.COM } else { 63310500SHai-May.Chao@Sun.COM continue; 63410500SHai-May.Chao@Sun.COM } 63510500SHai-May.Chao@Sun.COM } 63610500SHai-May.Chao@Sun.COM 63710500SHai-May.Chao@Sun.COM if (!found) { 63810500SHai-May.Chao@Sun.COM *mode = CRYPTO_FIPS_MODE_DISABLED; 63910500SHai-May.Chao@Sun.COM } 64010500SHai-May.Chao@Sun.COM 64110500SHai-May.Chao@Sun.COM out: 64210500SHai-May.Chao@Sun.COM (void) fclose(pfile); 64310500SHai-May.Chao@Sun.COM return (rc); 64410500SHai-May.Chao@Sun.COM } 645