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 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 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 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 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 * 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 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 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 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 * 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 * 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 * 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 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 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 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